應用移植指南
一,爲何要移植應用
SAE禁止IO寫操做,代碼目錄不能寫入。這意味着普通程序的上傳圖片、生成緩存等操做都不能在SAE上正常運行,這時候你須要對這些代碼進行修改後才能讓你的程序運行在SAE上。
SAE爲何要禁止IO寫操做?
SAE採用分佈式架構設計, 應用代碼將部署在多臺前端服務器上, 每次訪問請求可能到達不一樣服務器。(以下圖):
php
假設如今有A、B、C、D四臺服務器。用戶上傳一張圖片到A服務器,第二次訪問請求可能到達B服務器,此時將沒法獲取保存在A服務器上的圖片。
SAE使用MemcacheX、Storage等存儲型服務代替傳統IO操做,效率比傳統IO讀寫操做高,有效解決因IO瓶頸致使程序性能低下的問題。
另外,不少網站被攻擊都是由於服務器有寫的權限,程序代碼能被黑客修改,SAE禁止寫操做,也提高了服務器的安全性。
因此SAE爲了提高性能和安全,禁止本地IO寫操做。開發者可使用Storage,Memcache,KVDB等服務存儲需寫入的數據。
二,快速移植你的程序
使用Wrappers
SAE雖然禁止了IO寫操做,可是並無禁止fwrite,file_put_contents等寫操做函數,同時SAE還提供了Wrappers服務,這使得移植程序也比較簡單。 假設咱們要將下面的代碼移植到SAE上。
file_put_contents('test.php','');
include 'test.php';
?>
只須要給文件地址加上前綴就能夠了
file_put_contents('saemc://test.php','');
include 'saemc://test.php';
?>
若是地址的前綴爲saemc:// 表示在Memcache中進行讀寫操做 ,若是前綴爲saestor:// 表示在Storage中進行讀寫操做。前綴爲saekv://就是對KVDB的操做。這就是Wrappers的功能。
注意:
1,在使用Wappers前,須要先初始化相應的服務。
初始化Memcache:進入Memcache服務管理後臺 http://sae.sina.com.cn/?m=mcmng ,而後在網頁右上角「個人應用中」選擇指定應用。點擊「點此初始化MC」的按鈕就可初始化Memcache。
初始化Storage:進入Storage服務管理後臺http://sae.sina.com.cn/?m=storage ,選擇指定應用後 ,「點擊建立一個domain」按鈕進行建立。這裏容許建立多個domain, 開發者使用Wrappers將文件上傳到哪一個domain,取決於文件地址的第一個目錄名稱。 如 「saestor://upload/image/1.jpg」 這樣的地址,會將文件保存在名爲upload的domain中。
另外Mysql和KVDB也是須要先初始化才能使用,若是程序有用到這些服務,請先初始化。
2,操做頻繁的緩存不適合存儲在Storage中。
Storage讀寫效率比KVDB和Memcache低不少。操做頻繁的緩存不適合存儲在storage中,因此除操做用戶上傳的文件外,儘可能不要使用saestor://。
尤爲是一些程序代碼片斷的緩存。如上面的例子,若是使用如 include 'saestor://xxx' 的代碼來實現會使得程序性能較低。
理解了Wrappers的用法後, 就能夠開始移植程序了。
利用報錯快速定位
開發者能夠利用SAE的錯誤提示,快速的定位到程序須要修改的代碼。
首先保證你的應用開啓了錯誤提示。進入應用的「代碼管理」後臺http://sae.sina.com.cn/?m=vermng, 看看對應版本的「錯誤提示」是否開啓(默認是開啓的)。 還有檢查一下程序有沒有相似error_reporting(0)的代碼,屏蔽了錯誤提示。若是有,請先將他們註釋掉。
而後將程序上傳到SAE。若是有不兼容的地方,錯誤提示會告訴你具體文件的具體行。
若是出現相似這樣的提示:
SAE_Warning: file_put_contents(./xxx.php) [function.file-put-contents]: failed to open stream: Permission denied in xxx.php on line 2
說明程序正在進行IO寫操做, 只需給地址加上Wrappers的前綴,就能實現兼容。
若是你的程序的封裝性好,更改IO寫操做的代碼, 每每很簡單。好比ThinkPHP定義了RUNTIME_PATH常量。全部IO寫操做產生的文件都會存放在 RUNTIME_PATH常量指定的文件夾中, 移植ThinkPHP程序, 只須要更改RUNTIME_PATH常量,加上saemc:// 前綴就能夠了。其實其餘框架或封裝性比較好的程序,也是如此,只需更改一行代碼,就能兼容IO寫操做。若是你是從新用ThinkPHP開發程序的話,建議 使用SAE版ThinkPHP。
注:使用Wrappers後,有些操做是無效的。 好比file_exists ,你們能夠直接將這樣的函數註釋掉。
若是出現相似下面的提示:
SAE_Warning: mysql_connect() [function.mysql-connect]: this app is not authorised in xxx.php on line 2
說明程序正在使用Mysql數據庫,這時候須要初始化Mysql,並導入數據庫。你能夠在初始化後點擊「管理Mysql」按鈕,使用PHPMyAdmin進行數據導入。 當你數據比較大時,能夠用DeferredJob服務來導入。
導入數據庫後,還要將原程序中數據庫用戶名、密碼等更改成SAE的。 SAE的數據庫用戶名、密碼、數據庫名使用常量表示。能夠在mysql服務管理處看到。SAE的Mysql數據庫支持分佈式,能鏈接兩個數據庫。若是你的原程序只支持單數據庫操做,請鏈接主庫域名。
當你的程序在SAE上沒有出現錯誤提示了,你的程序已經初步能在SAE上面運行了。你還要檢查一下一些細節的功能是否實現。好比上傳圖片功能等。建議將上傳的圖片或其餘附件存放在Storage中。圖片存儲在Storage中後, 圖片的訪問地址也和之前不同。你須要使用Storage的getUrl方法得到圖片訪問地址,如:
$s=new SaeStorage();
$url=$s->getUrl('domain','filepath');//得到圖片地址,filepath爲圖片在storage中的路徑
?>
接下來,開發者能夠對程序進行進一步的優化,讓程序達到更好的性能。
三,性能優化
咱們提供了一些優化的建議。
1 IO操做產生的文件進行區分存儲
(1)建議將模板編譯緩存或其餘程序代碼片斷的緩存放在Memcache中,堅定反對將模板編譯緩存放在Storage中, 由於Storage的讀寫效率比Memcache低,將它們存入Storage會致使你程序運行較慢。
(2)將上傳的圖片或附件存儲在Storage中。若是你的圖片須要防盜鏈等功能, 你還能夠在SAE的服務管理後臺,經過設置domain的屬性能輕鬆的實現防盜鏈。
(3)將一些固定緩存存入KVDB中。有一些緩存不適合存儲在Memcache中, 由於Memcache中的緩存有可能會消失,好比Memcache空間不足時,最先存入Memcache中的緩存就會被刪除。因此你存入到Memcache的緩存,在讀取時必須須要判斷緩存是否存在,若是不存在從新生成。但有一些緩存生成一次後通常都不會變了,在讀取緩存的時候不用判斷它是否存在。 這類緩存建議使用KVDB進行存儲。
2 實現數據庫的讀寫分離
SAE MySQL數據庫主庫可讀寫,從庫只讀。查詢使用從庫消耗的雲豆更少,且響應更快,因此建議你們儘可能實現主從分離。如今不少框架,程序都支持讀寫分離,只需簡單配置便可。若是程序只支持單數據庫 能夠嘗試在執行SQL時進行判斷若是是Select則連從庫。
3 多使用SAE提供的服務
SAE提供了不少高效的服務,建議程序能使用SAE服務的地方儘可能使用SAE服務。好比程序有排行榜的功能, 可使用Rank服務實現;驗證碼的功能, 可使用SaeVCode服務;發送郵件的功能, 可使用Mail服務等等。請你們查看各個服務相關的文檔進行學習。
4 考慮使用原生接口
Wrappers當然方便簡單, 但它的效率確定不如原生的Memcache或Storage接口。若是你很在意效率問題, 能夠考慮使用原始接口實現移植。 使用原生接口實現移植的方法可參考:http://qing.weibo.com/1631767865/6142cd3933000cj9.html
四,常見問題
1 實現僞靜態
SAE不支持.htaccess文件,可是能夠經過AppConfig服務實現僞靜態。
2 生成靜態頁面
有些程序有生成純靜態html的機制。你們可使用KVDB存儲html靜態頁面數據,因爲SAE禁止IO寫操做,不能實現真正的純靜態,咱們能夠用僞靜態的方式到達一樣的效果,下面舉一個簡單的例子。
假設程序在未移植以前經過如下代碼生成html文件:
file_put_contents('html/index.html', 'htmlcontent');
?>
這樣用戶經過瀏覽器輸入地址 http://你的域名/html/index.html 訪問到的是一個純靜態頁面。
如今咱們要將程序移植到SAE上。
首先將html數據保存到KVDB上。
file_put_contents('saekv://html/index.html', 'htmlcontent');
?>
使用config.yaml, 寫一條僞靜態語句
- rewrite: if (path ~ "/html/(.*)") goto "/readhtml.php?path=html/$1"
若是用戶訪問了html目錄會僞靜態到readhtml.php文件進行讀取靜態數據。
readhtml.php的代碼爲:
echo file_get_contents('saekv://'.$_GET['path']);
?>
這樣,在SAE上用戶也能經過瀏覽器輸入地址 http://你的域名/html/index.html 訪問到數據。
3 日誌記錄。
有些程序有日誌記錄功能, 若是日誌讀寫太頻繁,不適合將日誌文件存入storage中,建議使用sae_debug實現日誌記錄。 可是sae_debug記錄日誌的同時也會向瀏覽器輸出日誌內容。不少程序但願能現實暗地記錄日誌, 你們能夠經過封裝函數實現。
如:
function sae_log($msg){
sae_set_display_errors(false);//關閉信息輸出
sae_debug($msg);//記錄日誌
sae_set_display_errors(true);//記錄日誌後再打開信息輸出,不然會阻止正常的錯誤信息的顯示
}
?>
經過sae_debug函數記錄的日誌能夠在應用管理後臺中的「日誌中心」查看,它屬於debug類型的日誌, 你們須要在搜索框中下拉菜單中選擇debug類型進行查看。
4 緩存共享問題
SAE每個應用能建立多個版本,可是這多個版本共用同一個Memcache,KVDB等 服務,有時候容易出現緩存共享問題。好比一個應用建立了兩個版本,放有相同的程序, 程序有模版緩存機制,可能會出現,只修改了版本1的模板,卻發現版本2的內容也被修改了。咱們要避免不一樣版本之間緩存名稱相同的現象。開發者可使 用$_SERVER['HTTP_APPVERSION']變量給緩存名稱加上應用的版本號
5 Memcache緩存須要有更新機制
Memcache緩存由於有消失的可能, 因此在讀取Memcache緩存時應該要判斷緩存是否存在,若是不存在從新生成緩存,不然的Memcache緩存一旦被刪除而程序又沒有更新緩存的機制,將可能致使網站不能正常訪問。開發者能夠在程序移植完成後在應用的Memcahe服務管理後臺手動清空Memcache緩存,再測試一下網站是否能正常運行。 建議將不須要更新機制的緩存使用KVDB存儲。
6 如何得到Storage的域名
有時候程序的圖片訪問路徑能夠定義前綴, 咱們只須要將前綴替換爲Storage的域名就能夠了。 得到Storage域名的方法:
$s=new SaeStorage();
$domain=rtrim($s->getUrl('domain',''),'/');//注意getUrl的第二個參數爲空
?>
7 有些地方不能用Wrappers
並非全部文件地址前加上Wrappers相應的前綴都能實現兼容。 好比如下代碼:
$img=imagecreatefrompng("http://sae.sina.com.cn/static/image/logo.beta.new.png");
//…通過了一些列的圖片處理函數處理…
imagepng($img,'saestor://upload/logo.png');//想經過Wrappers保存處理後的圖片
?>
上面的代碼是不能將圖片保存到storage中的。
開發者可使用臨時文件解決上面的問題。
$img=imagecreatefrompng("http://sae.sina.com.cn/static/image/logo.beta.new.png");
//…通過了一些列的圖片處理函數處理…
imagepng($img,SAE_TMP_PATH.'logo.png');//保存爲臨時文件
file_put_contents('saestor://upload/logo.png', file_get_contents(SAE_TMP_PATH.'logo.png'));
?>
因此要注意,雖然你們把程序中文件地址加上了wrappers的前綴,也要檢查一下 文件地址是否在用在了不支持Wrappers的函數上。
通常的文件操做函數都是支持Wrappers的,如file_put_contents,fwrite,file_get_contents,include,file_exists, filemtime,move_uploaded_file等等。 只有個別帶特殊功能的函數不支持Wrappers。
8 SAE禁用了一些函數和類
出於平臺安全性考慮,SAE禁用了一些函數了類,詳情查看
http://sae.sina.com.cn/?m=devcenter&catId=220
請使用功能相同的其餘函數代替禁用的函數,如可用SimpleXML代替DoMDocument實現XML解析。
五,提交到應用倉庫
開發者能夠將移植好的程序提交到SAE的應用倉庫, 這樣別人能夠經過應用倉庫一鍵安裝就能快速得到你的程序。
建議你們在移植程序的時候寫一篇「移植記錄」。提交應用時一併將移植記錄提交給咱們。這樣方便咱們審覈你的應用。
移植記錄須要寫清楚移植程序時哪些地方作了修改,使用了什麼SAE服務等。
提交到應用倉庫的更多細節請見 http://sae.sina.com.cn/?m=devcenter&catId=230
或直接訪問如下地址:http://sae.sina.com.cn/?m=apps&a=step_sae_apphtml