eZ Cluster unleashed
The return
Purpose and history

One eZ Publish on multiple servers, for:
Performance
Redundancy

Created for eZ Publish 3.8, vastly improved since then:
3.10: huge schema & feature improvements
4.2: new eZDFS cluster handler for NFS
4.2: Stalecaching mechanism for eZDB and eZDFS
4.7: Refactored binary index architecture

Matches the shared database for filesystem operations:
Inserting new data, expiring/deleting obsolete data
serving files through HTTP
Cluster handlers



           eZ DB                        eZ DFS

From eZ Publish 3.8           From eZ Publish 4.2

Stores metadata in DB         Stores metadata in DB

Stores data in DB (BLOBs)     Stores data on NFS

Easy to setup                 Requires an NFS server

Huge DB, harder to maintain   Maintenance is much easier
HTTP vs Internal calls

HTTP

Requests done through index_cluster.php
Serves files directly
A reverse proxy caches images & binary files

INTERNAL / KERNEL CALLS

Reads/writes cache items
Stores binary files
Configuration #1: file.ini

A cluster handler must be configured in a file.ini override:

1.[ClusteringSettings]
2.FileHandler=eZDFSFileHandler


1.# DFS Cluster Handler settings
2.[eZDFSClusteringSettings]
3.MountPointPath=var/nfs
4.DBBackend=eZDFSFileHandlerMySQLBackend
5.DBHost=localhost
6.DBName=labs_ezpublish_trunk_cluster
7.DBUser=root
8.DBPassword=root
Configuration #2: database


eZDB and eZDFS both require database tables

The same DB server can be used

Performance wise it is better to use another server

Schemas are available in
kernel/sql/*/cluster_*_schema.sql (mysql only, oracle's are in
the extension)
Configuration #3: clusterize


Existing local files must be moved to the cluster

This  is done using bin/php/clusterize.php

This script will copy/move images & binary files from the local
filesystem to the cluster

It must only be executed once for the whole cluster
Configuration #4: binary URLs rewriting


URL rewriting is required to "stream" clusterized binary files to
visitors:
   Images
   Binary files

They only affect known path for these types of files

To stream different files, new rules must be added

     RewriteEngine On
     Rewriterule ^/var/([^/]+/)?storage/original/.* /index_cluster.php [L]
     Rewriterule ^/var/([^/]+/)?storage/images/.*   /index_cluster.php [L]

     # Standard eZ Publish rewrite rules
     # ...
Configuration #5: binary files index


The cluster index handles binary files HTTP requests

It doesn't use the whole kernel in order to perform better
It was completely refactored in 4.7

Before 4.7                              After 4.7
Required custom file to be created      No custom files


Many files also located at root level   Documented



Duplicated logic among handlers         Common code has been refactored



Features weren't identical among        Features are (almost) perfectly
Configuration #5: binary files index, example

/**
 * Cluster configuration file
 */
define( 'CLUSTER_STORAGE_BACKEND',    'dfsmysqli'     );
define( 'CLUSTER_STORAGE_HOST',       'localhost'     );
define( 'CLUSTER_STORAGE_PORT',       3306            );
define( 'CLUSTER_STORAGE_USER',       'clusteruser'   );
define( 'CLUSTER_STORAGE_PASS',       ''              );
define( 'CLUSTER_STORAGE_DB',         'ezcluster'     );
define( 'CLUSTER_STORAGE_CHARSET',    'utf8'          );
define( 'CLUSTER_MOUNT_POINT_PATH',   '/opt/nfs/ez'   );
How cache is handled


Remote, clusterized files are copied locally

Before using a local file, eZ always checks if it is newer
than the remote one

When a cache file is generated, it is stored on the cluster,
and re-used by other nodes

expiry.php provides an intermediate method
API: reading clusterized files

1.$path = '/var/ezwebin_site/path/to/my/file.txt'


1.// read a text file, "instance" syntax
2.$contents = eZClusterFileHandler::instance( $path )->fetchContents();


1.// read a text file, "static" syntax
2.$contents = eZClusterFileHandler::instance()->fileFetchContents( $path );


1.// fetch a file (a binary one for example) to disk
2.$path = 'var/ezflow_site/storage/original/video/961d8a65efffdd93708cc23bc6398953.flv';
3.$handler = eZClusterFileHandler::instance( $path )->fetchUnique();


1.// ... use the file ... then delete it
2.$handler->deleteLocal( $uniquePath );


1.// reading metadata
2.$file = eZClusterFileHandler::instance( $someFile );
3.echo $file->size();
4.echo $file->mtime();
API: writing a file to the cluster


Again, the native PHP I/O API isn't cluster aware !
1.// stores the contents of the $contents variable to cluster
2.$path = 'var/ezwebin_site/file.txt';
3.$handler = eZClusterFileHandler::instance( $path );
4.$handler->storeContents( $contents, 'text', 'text/plain' );


1.// alternative "static" method: fileStoreContents()


1.// stores the contents of a local image as a clusterized file
2.$imagePath = 'var/ezwebin_site/path/image.png';
3.$handler = eZClusterFileHandler::instance();
4.$handler->fileStore( $imagePath, 'image', true, 'image/png' );
API: ViewCache !


ViewCache uses advanced methods of the cluster API

These method handle:
      
        cache retrieving and/or generation
      
        Concurrency
      
        stale caching

It can technically be used to manage custom cache !

Next: introducing the processCache() method
API: The processCache() method !


It can be used for custom developements too !

It will let you implement caching in your own extensions

It uses:
       
         a generate() callback that generates the dynamic
       content
       
         a retrieve() callback that retrieves valid cached
       content
API: The processCache() method, CODE !

1.$cacheFilePath = eZCachedModule::cacheFilePath( $Params );
2.$cacheFile = eZClusterFileHandler::instance( $cacheFilePath );
3.$Result = $cacheFile->processCache(
4.    array( 'eZCachedModule', 'retrieve' ),
5.    array( 'eZCachedModule', 'generate' ),
6.    null,
7.    null,
8.    compact( 'Params' ) );

1.return $Result;
API: The processCache() method, callback


Let's review an example that caches the whole output
($Result) of a module.
It has a configurable TTL, and provides a custom cache key
that can be used to invalidate cache.

1. Get the code from github:
git clone git://gist.github.com/3635993.git extension/ezcachedmodule


2. enable the extension in site.ini
ActiveExtensions[]=ezcachedmodule


3. and do not forget to regenerate the extensions autoload:
Php bin/php/ezpgenerateautoloads.php –extension
API: The processCache() method, callback


1. Enable the DebugOutput
  Come on, you know how to do it


2. Go to http://ezpublish4.admin/cachedmodule/view/abcd
  Look into the debugOutput for « eZCachedModule »


3. Let's review it together
API: The processCache() method, callback


Let's review an example that caches the whole output
($Result) of a module.
It has a configurable TTL, and provides a custom cache key
that can be used to invalidate cache.

1. Get the code from github:
git clone git://gist.github.com/3635993.git extension/ezcachedmodule


2. enable the extension in site.ini
ActiveExtensions[]=ezcachedmodule


3. and do not forget to regenerate the extensions autoload:
Php bin/php/ezpgenerateautoloads.php –extension

eZ Publish cluster unleashed revisited

  • 1.
  • 2.
    Purpose and history OneeZ Publish on multiple servers, for: Performance Redundancy Created for eZ Publish 3.8, vastly improved since then: 3.10: huge schema & feature improvements 4.2: new eZDFS cluster handler for NFS 4.2: Stalecaching mechanism for eZDB and eZDFS 4.7: Refactored binary index architecture Matches the shared database for filesystem operations: Inserting new data, expiring/deleting obsolete data serving files through HTTP
  • 4.
    Cluster handlers eZ DB eZ DFS From eZ Publish 3.8 From eZ Publish 4.2 Stores metadata in DB Stores metadata in DB Stores data in DB (BLOBs) Stores data on NFS Easy to setup Requires an NFS server Huge DB, harder to maintain Maintenance is much easier
  • 5.
    HTTP vs Internalcalls HTTP Requests done through index_cluster.php Serves files directly A reverse proxy caches images & binary files INTERNAL / KERNEL CALLS Reads/writes cache items Stores binary files
  • 6.
    Configuration #1: file.ini Acluster handler must be configured in a file.ini override: 1.[ClusteringSettings] 2.FileHandler=eZDFSFileHandler 1.# DFS Cluster Handler settings 2.[eZDFSClusteringSettings] 3.MountPointPath=var/nfs 4.DBBackend=eZDFSFileHandlerMySQLBackend 5.DBHost=localhost 6.DBName=labs_ezpublish_trunk_cluster 7.DBUser=root 8.DBPassword=root
  • 7.
    Configuration #2: database eZDBand eZDFS both require database tables The same DB server can be used Performance wise it is better to use another server Schemas are available in kernel/sql/*/cluster_*_schema.sql (mysql only, oracle's are in the extension)
  • 8.
    Configuration #3: clusterize Existinglocal files must be moved to the cluster This  is done using bin/php/clusterize.php This script will copy/move images & binary files from the local filesystem to the cluster It must only be executed once for the whole cluster
  • 9.
    Configuration #4: binaryURLs rewriting URL rewriting is required to "stream" clusterized binary files to visitors: Images Binary files They only affect known path for these types of files To stream different files, new rules must be added RewriteEngine On Rewriterule ^/var/([^/]+/)?storage/original/.* /index_cluster.php [L] Rewriterule ^/var/([^/]+/)?storage/images/.* /index_cluster.php [L] # Standard eZ Publish rewrite rules # ...
  • 10.
    Configuration #5: binaryfiles index The cluster index handles binary files HTTP requests It doesn't use the whole kernel in order to perform better It was completely refactored in 4.7 Before 4.7 After 4.7 Required custom file to be created No custom files Many files also located at root level Documented Duplicated logic among handlers Common code has been refactored Features weren't identical among Features are (almost) perfectly
  • 11.
    Configuration #5: binaryfiles index, example /** * Cluster configuration file */ define( 'CLUSTER_STORAGE_BACKEND', 'dfsmysqli' ); define( 'CLUSTER_STORAGE_HOST', 'localhost' ); define( 'CLUSTER_STORAGE_PORT', 3306 ); define( 'CLUSTER_STORAGE_USER', 'clusteruser' ); define( 'CLUSTER_STORAGE_PASS', '' ); define( 'CLUSTER_STORAGE_DB', 'ezcluster' ); define( 'CLUSTER_STORAGE_CHARSET', 'utf8' ); define( 'CLUSTER_MOUNT_POINT_PATH', '/opt/nfs/ez' );
  • 12.
    How cache ishandled Remote, clusterized files are copied locally Before using a local file, eZ always checks if it is newer than the remote one When a cache file is generated, it is stored on the cluster, and re-used by other nodes expiry.php provides an intermediate method
  • 13.
    API: reading clusterizedfiles 1.$path = '/var/ezwebin_site/path/to/my/file.txt' 1.// read a text file, "instance" syntax 2.$contents = eZClusterFileHandler::instance( $path )->fetchContents(); 1.// read a text file, "static" syntax 2.$contents = eZClusterFileHandler::instance()->fileFetchContents( $path ); 1.// fetch a file (a binary one for example) to disk 2.$path = 'var/ezflow_site/storage/original/video/961d8a65efffdd93708cc23bc6398953.flv'; 3.$handler = eZClusterFileHandler::instance( $path )->fetchUnique(); 1.// ... use the file ... then delete it 2.$handler->deleteLocal( $uniquePath ); 1.// reading metadata 2.$file = eZClusterFileHandler::instance( $someFile ); 3.echo $file->size(); 4.echo $file->mtime();
  • 14.
    API: writing afile to the cluster Again, the native PHP I/O API isn't cluster aware ! 1.// stores the contents of the $contents variable to cluster 2.$path = 'var/ezwebin_site/file.txt'; 3.$handler = eZClusterFileHandler::instance( $path ); 4.$handler->storeContents( $contents, 'text', 'text/plain' ); 1.// alternative "static" method: fileStoreContents() 1.// stores the contents of a local image as a clusterized file 2.$imagePath = 'var/ezwebin_site/path/image.png'; 3.$handler = eZClusterFileHandler::instance(); 4.$handler->fileStore( $imagePath, 'image', true, 'image/png' );
  • 15.
    API: ViewCache ! ViewCacheuses advanced methods of the cluster API These method handle:  cache retrieving and/or generation  Concurrency  stale caching It can technically be used to manage custom cache ! Next: introducing the processCache() method
  • 16.
    API: The processCache()method ! It can be used for custom developements too ! It will let you implement caching in your own extensions It uses:  a generate() callback that generates the dynamic content  a retrieve() callback that retrieves valid cached content
  • 17.
    API: The processCache()method, CODE ! 1.$cacheFilePath = eZCachedModule::cacheFilePath( $Params ); 2.$cacheFile = eZClusterFileHandler::instance( $cacheFilePath ); 3.$Result = $cacheFile->processCache( 4. array( 'eZCachedModule', 'retrieve' ), 5. array( 'eZCachedModule', 'generate' ), 6. null, 7. null, 8. compact( 'Params' ) ); 1.return $Result;
  • 18.
    API: The processCache()method, callback Let's review an example that caches the whole output ($Result) of a module. It has a configurable TTL, and provides a custom cache key that can be used to invalidate cache. 1. Get the code from github: git clone git://gist.github.com/3635993.git extension/ezcachedmodule 2. enable the extension in site.ini ActiveExtensions[]=ezcachedmodule 3. and do not forget to regenerate the extensions autoload: Php bin/php/ezpgenerateautoloads.php –extension
  • 19.
    API: The processCache()method, callback 1. Enable the DebugOutput Come on, you know how to do it 2. Go to http://ezpublish4.admin/cachedmodule/view/abcd Look into the debugOutput for « eZCachedModule » 3. Let's review it together
  • 20.
    API: The processCache()method, callback Let's review an example that caches the whole output ($Result) of a module. It has a configurable TTL, and provides a custom cache key that can be used to invalidate cache. 1. Get the code from github: git clone git://gist.github.com/3635993.git extension/ezcachedmodule 2. enable the extension in site.ini ActiveExtensions[]=ezcachedmodule 3. and do not forget to regenerate the extensions autoload: Php bin/php/ezpgenerateautoloads.php –extension