Laravel中扩展Memcached缓存驱动实现使用阿里云OCS缓存
Laravel是我最近用得非常多而且越用就越喜欢的一款PHP框架,由于没有向下兼容的历史包袱,完全面向对象的风格,借助Facades优雅的IoCContainer实现,采用Composer进行包管理,可以方便地引入和使用开源社区里的优秀组件……总而言之,这是一款真正让你能够"codehappy"的“巨匠级PHP开发框架”。
在尝试把自己的LaravelApp部署到阿里云的时候,遇到了一个问题:Laravel支持Memcached缓存,阿里云的OCS也是基于Memcached的缓存,但是阿里云OCS采用SASL认证,而Laravel的Memcached驱动并没有实现相关的方法,即使在服务器上编译PHPMemcached的时候启用了SASL认证选项,也没办法设定用户名和密码。
在Laravel中,解决这样的问题,有很多方法。我选择了最快捷最省事的方法:扩展Laravel自己的Memcached驱动,通过Memcached对象自身的setSaslAuthData方法,指定用户名和密码。
背景知识
这是利用了Illuminate\Cache\CacheManager的extend方法(继承自Illuminate\Support\Manager)。先看一下这个方法的定义:
/** *RegisteracustomdrivercreatorClosure. * *@param string $driver *@param Closure $callback *@return\Illuminate\Support\Manager|static */ publicfunctionextend($driver,Closure$callback){}
这个方法接收两个参数,第一个是代表你自定义的驱动名称的字符串,第二个是一个闭包回调函数,这个函数就是当调用你的自定义驱动时要执行的方法。通过阅读Illuminate\Cache\CacheManager的源代码,我们可以发现创建驱动的函数要返回一个Illuminate\Cache\Repository的实例,Illuminate\Cache\Repository的构造函数如下:
/** *Createanewcacherepositoryinstance. * *@param \Illuminate\Cache\StoreInterface $store */ publicfunction__construct(StoreInterface$store) { $this->store=$store; }
它需要一个实现了Illuminate\Cache\StoreInterface接口的对象,这个接口中定义了Cache对象能够执行的方法。由于我计划是扩展原有的Memcached缓存驱动,在Illuminate\Cache\CacheManager的源代码中,可以看到Laravel是这样创建Memcached驱动的:
/** *CreateaninstanceoftheMemcachedcachedriver. * *@return\Illuminate\Cache\MemcachedStore */ protectedfunctioncreateMemcachedDriver() { $servers=$this->app['config']['cache.memcached']; $memcached=$this->app['memcached.connector']->connect($servers); return$this->repository(newMemcachedStore($memcached,$this->getPrefix())); }
它先从配置文件中读取你定义的Memcached服务器,然后创建一个Memcached对象(通过Illuminate\Cache\MemcachedConnector实现,实际上就是创建一个标准的Memcached对象,然后调用Memcached的addServer方法来指定要连接的服务器,然后返回实例化的Memcached对象。)
扩展自己的缓存驱动
了解了上述的背景知识之后,就可以来扩展自己的缓存驱动了。思路如下:
1.在app/config/cache.php文件中,增加三个配置项,用来设定“是否使用sasl认证”,“sasl认证账户”,“sasl认证密码”。
2.在bootstrap/start.php文件中,调用Cache::extend方法扩展驱动。
3.在app/config/cache.php文件中,修改driver配置项,指定系统使用自己扩展的驱动。
增加配置项
首先,打开app/config/cache.php文件,找到:
'memcached'=>array( array('host'=>'127.0.0.1','port'=>11211,'weight'=>100), ),
修改为:
'memcached'=>array( array('host'=>'127.0.0.1','port'=>11211,'weight'=>100), ), 'memcached_sasl'=>'true',//启用sasl认证 'memcached_user'=>'yourocsusername',//你的OCS用户名 'memcached_pass'=>'yourocspassword',//你的OCS密码
扩展驱动
然后,打开bootstrap/start.php文件,在最后一行return$app;前面插入代码:
//基于系统自己的Memcached缓存驱动,扩展一个名为saslMemcached的缓存驱动 Cache::extend('saslMemcached',function($app){ //从配置文件中读取Memcached服务器配置 $servers=$app['config']['cache.memcached']; //利用Illuminate\Cache\MemcachedConnector类来创建新的Memcached对象 $memcached=$app['memcached.connector']->connect($servers); //如果服务器上的PHPMemcached扩展支持SASL认证 if(ini_get('memcached.use_sasl')){ //从配置文件中读取sasl认证用户名 $user=$app['config']['cache.memcached_user']; //从配置文件中读取sasl认证密码 $pass=$app['config']['cache.memcached_pass']; //禁用Memcached压缩(阿里云的文档里这样做了……) $memcached->setOption(Memcached::OPT_COMPRESSION,false); //指定Memcached使用binaryprotocol(sasl认证要求) $memcached->setOption(Memcached::OPT_BINARY_PROTOCOL,true); //指定用于sasl认证的账号密码 $memcached->setSaslAuthData($user,$pass); } //从配置文件中读取缓存前缀 $prefix=$app['config']['cache.prefix']; //创建MemcachedStore对象 $store=new\Illuminate\Cache\MemcachedStore($memcached,$prefix); //创建Repository对象,并返回 returnnew\Illuminate\Cache\Repository($store); });
修改配置,使用自己扩展的缓存驱动
打开app/config/cache.php文件,找到:
"driver"=>"file",//默认是使用文件缓存
修改为:
"driver"=>"saslMemcached",//刚才扩展实现的驱动名称
现在,你就可以在你的阿里云ECS服务器上,让Laravel使用阿里云OCS缓存服务了。(前提是你的PHP支持Memcached扩展,并且启用了SASL认证,参考:http://help.aliyun.com/doc/view/13553932.html