When and how caching can save your site. Part 2: authenticated users
On my last blog post we looked to what Drupal achieves out of the box regarding Drupal caching. We understood how Drupal can cache pages for anonymous users and found solutions to avoid to bootstrap Drupal to serve a cached page (using a reverse proxy like Varnish or redirecting requests using Boost). We also saw that even if any of these tools is used, Drupal is also able to save cached versions of pages in the database. However, Drupal allows to plug transparently other caching backends that are faster:
- Memcache is the most popular option to be used as Drupal caching backend. It is well supported by contributed modules and it is available to be used on Acquia Cloud. Memcache can be easily scaled to several boxes and memcache module allows assigning each Drupal cache type to a different cache bin. This allow to deploy the different bins in the different servers for instance without troubles. Memcached should however always live as close as possible to the web server, ideally even in the same box. Memcache is highly recommended for environments where partial caching is needed for authenticated users for instance.
- APC is another option to store cached keys. APC is a popular opcode cache extension for PHP that can easily improve the performance of any website by caching in memory php scripts and avoid to read them from the disk. In a framework like Drupal that load many php files in each request, having APC installed is almost a must. Moreover, APC provides a keystore caching feature that can be used as a Drupal caching backend. Even if using APC might be fast then using memcache, the fact that it can not scale across several servers and in some configurations the memory allocated by a php process can not be shared with other processes, presents a significant disavantage when compared with memcached.
- Other options include Redis , Filecache or MongoDB . All of them have modules available for Drupal in different stages of maturity, available for different versions in D6 and D7, providing different levels of support for Drupal caching.
A new caching backend for Drupal can help on speeding render of partial parts of Drupal pages, like blocks, views and nodes.
Replacing the default Drupal backend engine is most of the times a straightforward process of configuring settings.php to support a different caching backend and the settings needed by that backend. For memcache for instance you would use:
$conf['cache_backends'] = 'sites/all/modules/memcache/memcache.inc';
$conf['cache_default_class'] = 'MemCacheDrupal';
Apart from providing high level page caching, Drupal can also cache different parts used in page generation. Those parts can be cached and reused the next times they are needed. Drupal core and popular modules are able of caching their results, both for anonymous and authenticated users, for instance:
- Content caching: Node generation can be cached assuming that fields look similar to different users.
- Block caching: Blocks can be deployed in several parts of pages and their results can be cached globally, or cached per page, roles or users.
- Menus and menu links: Instead of gathering information about menus and menu links on all requests, their serialized version can be cached and reused.
- Views: Views are usually used to grab results from the database and show them in different contexts of Drupal pages. Views module is able of caching rendered results or intermediate results that were grabbed from the database and still need to be rendered. Views caching API is smart enough to understand the context the view was generated: exposed filters and arguments can influence the view end result. Therefore when caching is active, filters and arguments are used as part of the caching key to guarantee that caching results are not saved wrongly.
Page caching for authenticated users
There is another solution to provide caching for authenticated users for Drupal 6. One of the factors that influence what users see in different pages are their permissions. Permissions in Drupal are controlled by roles and roles are assigned to users. In theory this allow site builders to define groups of users that would see different things in different pages, and therefore could always receive the same version of the page.
This is the reasoning behind authcache module. The module registers an extra cookie when the user logins with the user roles hashed in a key. Therefore without going to the database in each request the module can identify which roles do users have. The module allows configuring cached pages to be saved and served to different roles (from anonymous users, authenticated users and any other Drupal role). The module allows also configuring which paths should be cached or excluded from general caching strategy.
When a request is made the module would identify if the page could be cached for that path and that specific role. If that is valid that the page could have been cached, then Drupal accesses caches to analyze if a valid cached version is available. If the cached version is available, it is served directly to the users, if not it is normally rendered and it is saved to be served in the next request.
Authcache also saves extra cookies with values for user name and user email that can be used to be printed in the page template.
Authcache works as a wrapper caching backend that integrates well with other caching backends (Memcached and Cacherouter). Its installation is straight forward as you would be expecting, settings about the used caching backend will be automatically recognized:
$conf['cache_inc'] = './sites/all/modules/authcache/authcache.inc';
Authcache will automatically try to include the Cache Router or Memcache file include. If you are using a different cache module, you can define its path by setting:
$conf['cache_inc_via_authcache'] = './sites/path/to/module/cacheinclude.inc';
The module configuration page located in the administrative performance settings page allows to configure all settings related with paths, roles and cache options. A debug mode is available to show to specific roles debug information that can help on understanding if caching is being set correctly. Authcache is currently stable for Drupal 6 and in active development for Drupal 7.
Avoiding the bootstrap
Normally when partial caching is used, Drupal needs to bootstrap to load the different cached elements which can still cost cpu time. Nevertheless, this can be avoided using Edge Side Includes and Varnish for instance: specific elements or blocks can be loaded each time a page loaded trough an internal call to the backend server. This can in help in situations where all the page need to be cached but a specific element need to have different caching settings or be totally customized according to the context. There are modules that can provide ESI integration with Drupal and can render several types of elements in paths that can be included in Edge Side Include calls. In a near future in Drupal 8 it is expected that render several elements via ESI calls gets much easier. That is one the main goals of the WSCCI initiative that you can follow in http://groups.drupal.org/wscci.