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的支持。