ThinkPHP正式发布了云引擎版本,本篇就简单说明下如何使用云引擎扩展。
概述
ThinkPHP的云引擎扩展是为云平台服务的ThinkPHP扩展。通常所说的云平台是指PaaS类型的云计算平台(服务),他们的名称一般叫App Engine 。如新浪的有SAE(Sina App Engine) ,百度有 BAE(Baidu App Engine),等等。
可以看到当今云计算已经十分流行,但是云计算有两个缺点。
学习成本高: 我们要学习云计算提供的服务怎么使用,每使用一个云平台都需要学习一次。
平台不兼容: 因为我们使用了这个云平台的服务,其他云平台没有和它相同的服务,导致我们的程序对此云平台有依赖, 不能移植到其他云平台,也不能移植到普通环境。
ThinkPHP的引擎扩展出现的目的就是为了解决云计算的两大缺点。降低用户学习成本,让用户只要会使用ThinkPHP就能用所有的云平台,我们还是按照传统使用ThinkPHP的方式,但你已经不知不觉使用了云计算的服务。解决平台兼容性问题,同样的代码既能在普通环境运行,也能在各种云平台上运行。
ThinkPHP原来的SAE引擎,只适合在SAE平台下使用,不能在其他云平台下使用,所以只是一种支持云平台的探索,而Cluster引擎扩展适合所有云平台以及分布式集群环境。
Cluster引擎采用IO分离的机制,实现了一个引擎扩展,通用所有云平台,所有分布式环境,普通环境下也可以运行,真正的打破了云平台不兼容的缺点。开发人员用ThinkPHP的Cluster引擎写出的程序将彻底摆脱对云平台的依赖,从而实现一次编码,多处(云平台)部署。
下载
我们首先需要下载Cluster引擎扩展,选择下载其中任意一个:
云引擎扩展单独下载ThinkPHP云引擎版本下载如果是下载的引擎扩展,下载后解压缩放入系统的Extend/Engine/目录。
云引擎版本则集成了最新github版本的3.1.2核心包和最新的Cluster引擎扩展,以及常用的驱动和类库扩展。
入口文件定义
新版的引擎扩展无需在入口文件中载入引擎入口文件,和使用标准模式一样载入框架入口文件即可,然后在入口文件定义常量ENGINE_NAME为引擎扩展的名称即可,如定义为:
<?php
define('APP_NAME','App');
define('APP_PATH','./App/');
define('THINK_PATH','./ThinkPHP/');
define('ENGINE_NAME','cluster');
require THINK_PATH.'ThinkPHP.php';
然后在本地运行你的代码,生成项目目录。
注意:项目目录一定要在本地生成,不可在云平台下生成, 因为云平台往往是不可写的环境。上传代码到云平台
然后将你生成的项目目录和文件以及ThinkPHP的核心文件上传到云平台。因为ThinkPHP Cluster引擎在云平台下不会生成任何文件,因此你无需上传项目的Runtime目录。
下面以SAE和BAE为例,说明如何上传代码到云平台。
上传代码到SAE
将代码上传到SAE可以参考SAE文档:
http://sae.sina.com.cn/?m=devcenter&catId=212上传代码后,还需要开启一些服务。
开启Memcahce服务进入SAE的应用列表:
http://sae.sina.com.cn/?m=myapp 选择你刚才上传代码的应用。 然后在网站左侧的服务管理处 点击Memcache,然后开启Memcahe服务即可。
ThinkPHP Cluster在SAE平台使用Memcache存储核心编译缓存,模板缓存以及S缓存。你不用学习SAE的Memcache服务怎么使用, 如果你需要使用Memcache,使用ThinkPHP的S函数即可。
开启KVDB服务开启KVDB服务和开启Memcahce服务一样,也需要在服务管理处进行开启。
ThinkPHP Cluster将静态缓存,F缓存存入了KVDB,你不用学习SAE的KVDB怎么使用,如果需要使用KVDB,使用ThinkPHP的F函数即可。
创建StorageThinkPHP上传文件使用UploadFile.class.php。 在SAE上一样是使用UploadFile类上传文件,用法不变。只是SAE是不可写的环境,文件不会被上传到代码空间而是上传到了Storage 。 我们需要在SAE服务管理处创建storage , storage的domain名称和你的上传路径相关,是你上传路径中的第一个文件夹名称。 比如我们的上传代码如下:
import("@.ORG.UploadFile");
$config=array(
'allowExts'=>array('jpg','gif','png'),
'savePath'=>'./Public/upload/',
'saveRule'=>'time',
);
$upload = new UploadFile($config);
if(!$upload->upload()){
$this->error($upload->getErrorMsg());
}
因为上传路径为'./Public/upload/' 第一个文件夹名词为Public, 所以我们需要在SAE创建storage的domain名词为public,然后这段上传代码在本地也能运行,在SAE上也能运行,在SAE上文件被上传到了storage中。
注:1,SAE平台storage的domain不区分大小写,统一小写, 所以domain名称Public 可以不用首字母大写。
2,使用的UploadFile类,请使用首次运行代码生成项目目录中的Lib/ORG/UploadFile.class.php文件,这个文件已经被修改适合所有云平台。将代码上传到BAE
一样的代码,不仅能上传到SAE,上传到BAE也可以运行,上传到所有其他云平台也可以运行。但BAE目前还在内测,使用需要先获得邀请码, 如果你无法使用BAE,可以测试一下我们已经部署在BAE上的应用:
http://tpcluster.duapp.com/ BAE和SAE一样也可以使用SVN部署代码,在创建应用后会获得一个SVN地址。
上传完代码后,需要开启一些服务。
开启cache服务进入你的管理中心
http://developer.baidu.com/dev 进入你刚才上传的应用,在左侧的服务管理处点击cache服务。
然后初始化服务即可。BAE的cache服务实际也是Memcache实现的。
ThinkPHP在BAE上将核心缓存,模板缓存,S缓存存入了Memcache, BAE并没有像SAE的KVDB那样的nosql服务,所以F函数,静态缓存也都存入了Memcache(过期时间是0,永不过期)。
注意: BAE虽然并没有像SAE那样强制环境为不可写的环境。但是我们不要在BAE上写入文件,因为云平台都是分布式环境,写入的文件很容易读取不到。开启云存储服务和SAE一样,ThinkPHP在BAE上传文件一样使用UplaodFile类,用法不变。但在BAE文件是被存在云存储中。
在管理中心的左侧点击“我的云服务” , 在新打开的页面的左侧菜单中点击“云存储”,在这里需要创建bucket, 这里的bucket 就相当于是SAE storage的domain。 Bucket的名称和你的上传路径相关,是你路径中的第一个文件夹名称。 如果上传路径是 ./Public/upload/ 按理说 我们要建立一个名为public的bucket,但是BAE的存储的bucket要求是全局唯一的, 别人创建了一个名为public的bucket,你就不能再创建了。 所以我们要加上前缀。 假设我们的前缀为“think-” , 创建的bucket名词为 “think-public” (和SAE一样,名词全部小写) 。 而这个think- 的前缀需要在 BAE配置文件中配置。编辑你项目目录下 Conf/config_bae.php 文件,配置
'BUCKET_PREFIX'=>'think-'
使用专用文件
我们知道,如果在本地上传一张图片到 ./Public/upload/目录下, 要显示图片,模板中的代码如下:
<img src="/Public/upload/{$filename}" />
而在SAE和BAE上图片并没有存在该上传目录下,上面的代码能正常显示图片吗?在ThinkPHP云引擎中实现了不管是在普通环境还是云平台,使用的代码都一样, 在云平台还是像普通环境那样使用代码, 上面显示图片的代码,在云平台也能正常显示。原理是利用了云平台专用文件。
各个平台都会有一些差异,我们尽量不要在我们的代码中带入平台特征,比如显示图片如果写为
<img src="http://appname-public.stor.sinaapp.com/upload/{$filename}">
那么只能显示在SAE平台下上传的图片,普通环境,BAE将无法显示。因为图片地址中使用了SAE storage的域名,带入了SAE平台的特征。 如果代码中带入平台特征就会导致代码没有可移植性,本地调试也很困难。但是各个平台有都各有差异,我们将差异写入专用文件中,不在普通文件中体现,这样就能兼容全平台的。
专用文件是指在不同平台下会加载这个平台专用的文件, 如前面提到的config_bae.php 配置文件一样只在BAE会加载, 在其他平台不会加载。
专用文件有两种配置文件和函数文件。
(1)配置专用文件
在项目的Conf文件夹下config_sae.php文件中的配置项是SAE平台才会加载的配置。
config_bae.php文件中的配置项在BAE中才会加载。 配置专用文件会后于项目配置文件(config.php) 加载。 如果有相同配置项,后加载的会覆盖先加载的。 比如config.php和config_sae.php都有数据库配置项。 在sae下数据库配置以config_sae.php中的值为准,而在普通环境,因为不会加载config_sae.php, 数据库配置项还是config.php中的值。我们知道SAE和BAE下数据库配置都是常量,所以可以把数据库配置写死在配置专用文件中, SAE的配置专用文件还实现了数据库的主从读写分离。 而config.php中的数据库信息可以写成你在本地开发时的数据库,这样每次上线代码都不用修改配置。
首次在本地运行代码时生成的默认项目中已经为大家创建好了SAE和BAE的配置专用文件。默认的配置专用文件中除了配置了数据库相关配置项,还实现了图片显示的兼容,是利用ThinkPHP模版替换变量功能实现的。模版替换变量的配置项是TMPL_PARSE_STRING显示图片代码为:
<img src="/Public/upload/{$filename}" />
其中/Public 就是一个模版替换变量, 他一般为替换为 /Public 然后我们再配置专用文件中配置了将 '/Public/upload'替换为file_domain ('Public').'/upload'
file_domain () 函数在SAE用于获得storage的域名, BAE用于获得云存储的域名。 这个函数需要传递一个参数, SAE下传递storage的domain,BAE下传递的是buncket的名称。
通过上面的手段就实现的显示图片的代码在各个平台的兼容。
注:BAE不支持pathinfo,所以在BAE的配置专用文件中还配置了URL_MODEL 为3 的兼容模式。 (2)函数专用文件
除了配置文件,你还可以建立不同平台的函数文件。在项目的 Common文件下 common_sae.php是SAE的函数专用文件,在SAE平台下才会加载, common_bae.php是BAE的函数专用文件,在BAE平台下才会加载, common_local.php 是普通环境的函数文件,在本地运行时才会加载。 如果我们有一个操作在不同平台的实现方式都不一样,那么我们把它封装成函数, 在各个函数专用文件中实现同名的函数。这样也实现了全平台兼容。
云引擎增加的常量
在云引擎扩展中,为了方便使用,增加了相应的常量。
IS_SAE | 判断是否为SAE平台 |
IS_BAE | 判断是否为BAE平台 |
IS_CLOUD | 判断是不是云计算平台(在SAE,BAE下都为true,在本地环境下为false) |
通过以上常量,可以判断不同平台进行不同操作。
测试应用
首次运行代码默认创建的项目中有些简单的测试例子,包括S函数,F函数,文件上传,日志记录等。大家都可以在各个平台测一测。 注意日志记录各个平台记录的地方不一样, SAE是记录到了日志中心,查看日志时需要类型为debug类型。
BAE是记录在BaeLog中,需要选择类型为debug。
引擎定制
ThinkPHP的Cluster引擎不光适合于云平台,所有分布式的环境都适合,云平台也一般是分布式的环境。 他们共同的特点都是环境不让直接写入文件(限制IO写操作)。原因很简单,因为他们是分布式的环境,每次访问都可能是访问在不同的服务器上面,而写操作是单机的, 比如程序在A服务器写入了一个文件test.txt,而下次访问可能是访问到了B服务,B服务并没有test.txt,读取test.txt就会失败。各个平台的最大差异就是把程序写入的文件内容存储在哪儿。
注:BAE环境当流量大时才会触发分布式模式,流量小一直运行在单机模式中,所以你可以在BAE上测试读取写入文件,可能不会出现读取失败的现象,只有当到达一定流量才会看见。ThinkPHP Cluster 采用IO分离的机制, 将IO操作交给了用户实现,从而实现了对不同平台的兼容的。 我们进入默认创建的项目中,可以看见多了一个IO文件夹, 该文件夹下 sae.php 文件实现了SAE平台的IO操作, bae.php实现了BAE平台的IO操作,auto.php文件能智能判断云平台加载不同的IO文件, Cluster默认就是加载的auto.php。 sample.php 文件是一个IO文件的例子。如果你要在自己的分布式环境下运行代码,你需要参考sample.php 创建自己得IO文件。 然后在入口文件中定义IO_NAME常量,指定加载的IO文件。 如定义为
define('IO_NAME','sample');
这时候程序运行时会加载sample.php 。 如果没有定义IO_NAME ,IO_NAME的默认值为auto。 我们如果定义
define('IO_NAME','sae');
这样程序只能在SAE和普通环境上运行,不能在BAE上运行了。
所以,要支持不同的云平台,只需要编写不同的IO文件就行了。
编写IO文件在IO文件中,我们要实现以下函数:
runtime_set($filename,$content), 在写入核心缓存或者模版缓存时会调用这个函数,函数传递了要存的文件路径和文件内容,你需要在这个函数中定义缓存内容存放在哪里。函数返回true表示存储成功,false表示存储失败。你可以将内容存储在memcache等分布式缓存中。
runtime_get($filename), 获取缓存的文件内容,函数需要返回存储的文件内容。
runtime_delete($filename), 删除缓存文件的方法,删除成功返回true,失败返回false。
F_set($name,$vlaue), F缓存存储方法,F缓存一般是需要持久化的,建议存储在redis,mongodb等能持久化存储数据的地方。 成功返回true,失败返回false
F_get($name), 获得设置的F缓存。返回缓存内容
F_delete($name), 删除F缓存,删除成功返回true,失败返回false。
S_set($name,$value,$expire), S缓存存储方法, S缓存建议存储在具有过期机制的缓存中(如memcache)。 成功返回true,失败返回false
S_get($name) ,获得设置的S缓存。返回缓存内容
S_delete($name),删除设置的S缓存。 成功返回true,失败返回false
S_clear(), 清空所有S缓存的方法。成功返回ture,失败返回false
file_upload($src_file,$desc_file), 实现文件上传, 传递参数src_file为准备上传的文件地址, $desc_file 是文件的保存地址。 上传成功返回true,失败返回false
file_delete($filename), 实现文件的删除,成功返回true,失败返回false。
file_domain($domain), 获得显示图片地址的根路径, 这个函数前面已经在配置专用函数中使用过, 而这个函数的实现是在IO文件中实现。
html_set($filename,$content) , 存储静态HTML内容,成功返回true,失败返回false
html_get($filename), 获得静态html内容。一旦我们设置静态缓存后会触发html_set 和html_get函数。
log_save($logs,$request_info), 日志保存方法, 传递的参数logs是一个数组,它是单次请求的所有日志, request_info 是这次请求的信息包括了请求时间,客户端ip等。
log_write($log), 写入单条日志。
注:只有当DATA_CACHE_TYPE 配置项为file时,对S缓存操作时才会触发S_set,S_get,S_delete 这些函数。 如果DATA_CACHE_TYPE 系统默认为file,如果你设置了这个配置项不为file,那么S缓存的实现为你指定的缓存类型。 RoadMap
现在ThinkPHP云引擎已经有了SAE和BAE的IO文件,还将计划添加腾讯TAE、 阿里云ACE、盛大云等IO文件。
更多描述,还可以参考视频说明:
http://v.youku.com/v_show/id_XNTA2NjU0OTg4.html。
关于云引擎我们还会不断的完善和改进,也非常欢迎大家反馈和建议,最后感谢大家对ThinkPHP的支持。