本文來自Mobingi官方技術專欄,歡迎關注php
本文翻譯自Scripting Languages for AWS Lambda: Running PHP, Ruby, and Gohtml
備註:Go已經在2018/01/15成爲了AWS Lambda原生支持的語言,你能夠從這裏瞭解到更多信息aws.amazon.com/blogs/compu…node
在與合做夥伴與顧客一塊兒的平常工做中,咱們看到過不少不一樣領域、不一樣尋常的專業技能和經驗,以及不少不一樣的編程語言。這些語言有些很老舊,而有一些很是前沿,不少團隊都對它們的其中之一專研頗深,他們極可能想,在AWS上的新組件,好比AWS Lambda上也使用這些語言。react
Lambda自己對不少語言提供原生支持,例如Java、Node.js、Python和C#。在這篇文章中咱們想描述如何在Lambda中使用其餘的腳本語言(非原生支持的)。c++
對於每個你想要使用的語言,你須要完成下面的任務:編程
準備: 從AMI啓動一個實例,而後用SSH登錄。json
編譯: 打包你要在Lambda使用的語言windows
安裝: 建立Lambda包並測試代碼運行安全
每一個編程語言的準備和安裝步驟基本相同,因此咱們在這裏只提供PHP、Go、和Ruby的,一步一步編譯打包的例子。ruby
Lambda容許你在Lambda運行環境中執行任何可執行文件。下面的步驟只是一個如何運行PHP、Go、Ruby在Lambda上面的大框。無論怎麼說,你仍是能夠用這個方法,添加一些特定的庫,擴展編譯範圍,使用JSON將你的Lambda函數和Amazon API Gateway或者其它服務互聯。
在編譯好二級制文件,並設定好基礎文件結構以後,你就不須要再新建項目或者修改代碼的時候重複作這些步驟。只須要簡單編寫代碼接受STDIN的標準輸入,而後輸出結果到標準輸出STDOUT,寫好的Node.js包裝器將會負責鏈接你的輸入輸出到運行環境。
爲了簡單起見,咱們僅演示準備PHP的步驟,但這些步驟一樣適用於後面描述的其餘運行環境。
在EC2控制檯,選擇Lanch instance,選擇AMI時,請使用在Lambda Execution Environment and Available Libraries中的一個AMI,請設定你想要運行PHP代碼和啓動EC2的區域。有關更多信息,請參閱Step 1: Launch an Instance。
選擇t2.large實例類型,它具備兩個內核和8 GB內存,能夠縮短PHP編譯時間。
選擇Review and Launch,使用存儲的默認值,而且把實例加入到一個只開放SSH訪問的由嚮導生成的安全組中。
選擇Launch繼續;在啓動對話框中,您能夠爲登陸選擇現有的密鑰對值,也能夠建立一個新的密鑰對值。在這個例子中,咱們建立一個名爲php
的新密鑰對並下載它。
下載密鑰後,命令行進入到文件所在的文件夾並運行如下命令:
chmod 400 php.pem
複製代碼
基於SSH的安全標準,咱們必須修改祕鑰權限。如今可使用EC2的公共DNS鏈接到實例。在控制檯中選擇實例並在屏幕右下方的公共DNS下查找實例,得到地址。
ssh -i php.pem ec2-user@[PUBLIC DNS]
複製代碼
當實例啓動並運行後,你就在一個適當的區域中有了一個適當AMI,你能夠用上面的命令登錄實例,繼續執行其餘步驟。
登陸到正在運行的AMI後,你能夠從源代碼編譯PHP7環境,並準備好爲Lambda環境打包。
下一步是編譯PHP7,將PHP7編譯器的輸出配置到指定目錄,最後編譯PHP7到Lambda AMI。
運行如下命令更新程序包管理器:
sudo yum update –y
複製代碼
安裝最少的必要的庫,用於編譯PHP7:
sudo yum install gcc gcc-c++ libxml2-devel -y
複製代碼
安裝依賴項後,您須要從PHP Downloads下載可用的PHP 7源代碼。
在這個例子中,咱們在愛爾蘭運行一臺EC2,所以咱們選擇了http://ie1.php.net/get/php-7.0.7.tar.bz2/from/this/mirror做爲咱們的鏡像。運行如下命令將源下載到實例,讀者能夠根據你的Instance所在的區域選擇本身的鏡像。
cd ~
wget http://ie1.php.net/distributions/php-7.0.7.tar.bz2 .
複製代碼
使用如下命令提取文件:
tar -jxvf php-7.0.7.tar.bz2
複製代碼
上面的命令在你的home目錄中建立php-7.0.7文件夾,而後經過下面的命令,建立一個專用的php-7二進制文件。
mkdir /home/ec2-user/php-7-bin
cd php-7.0.7
./configure --prefix=/home/ec2-user/php-7-bin/
複製代碼
這能夠確保PHP編譯很好地打包到您在home目錄中建立的指定PHP文件夾中。請記住,咱們只在此處編譯最基本PHP以減小Lambda函數的依賴。
你可使用./configure中提供的選項爲Lambda中PHP二進制文件加入更多依賴項或者編譯器選項。 運行./configure -h能夠獲取有關能夠打包到PHP發行版中的內容的更多信息。但請記住,這將增長PHP二進制包的總體大小(可能影響PHP Lambda代碼的總體啓動時間,譯者注)。
最後,運行如下命令,開始編譯:
make install
複製代碼
編譯完成後,能夠經過運行如下命令快速確認PHP是否正常運行:
cd ~/php-7-bin/bin/
./php -v
PHP 7.0.7 (cli) (built: Jun 16 2016 09:14:04) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
複製代碼
使用你最喜歡的編輯器,建立一個入口PHP文件,在這個例子中,咱們從Linux管道讀取輸入,獲取一個簡單的JSON文檔,並計算此JSON數據的頂層節點數量,將結果輸出stdout。
<?php
$data = stream_get_contents(STDIN);
$json = json_decode($data, true);
$result = json_encode(array('result' => count($json)));
echo $result."\n";
?>
複製代碼
既然PHP的編譯和準備已經就緒了,如今須要作的就是建立Lambda包,而後將Node.js包裝器做爲入口點。
首先,使用如下命令對二進制文件所在的php-7-bin文件夾進行tar壓縮:
tar -zcvf php-7-bin.tar.gz php-7-bin/
複製代碼
而後,退出遠程主機,x運行下面的命令如下載壓縮文件到本地計算機(Linux、OSX或者在windows上用相似WinSCP的工具)
scp -i php.pem ec2-user@[EC2_HOST]:~/php-7-bin.tar.gz .
複製代碼
下載玩壓縮包以後,新建一個Lambda項目,將全部文件解壓縮到此文件夾中,項目的目錄結構以下:
php-lambda
+-- php-7-bin
複製代碼
下一步是建立一個Node.js包裝器文件。該文件接受Lambda調用的輸入,使用helloLambda.php做爲參數調用PHP可執行文件,並經過Linux管道向PHP提供輸入以進行處理。複製以下內容到php.js:
// Javascript
process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT'];
const spawn = require('child_process').spawn;
exports.handler = function(event, context) {
//var php = spawn('php',['helloLambda.php']); //local debug only
var php = spawn('php-7-bin/bin/php',['helloLambda.php']);
var output = "";
//send the input event json as string via STDIN to php process
php.stdin.write(JSON.stringify(event));
//close the php stream to unblock php process
php.stdin.end();
//dynamically collect php output
php.stdout.on('data', function(data) {
output+=data;
});
//react to potential errors
php.stderr.on('data', function(data) {
console.log("STDERR: "+data);
});
//finalize when php process is done.
php.on('close', function(code) {
context.succeed(JSON.parse(output));
});
}
//local debug only
//exports.handler(JSON.parse("{"hello":"world"}"));
複製代碼
最終,全部文件結構以下:
php-lambda
+-- php-7-bin
-- helloLambda.php
-- php.js
複製代碼
部署以前的最後一步是將項目壓縮成能夠上傳到Lambda上的壓縮包LambdaPHP.zip。若是你想,能夠從php-7-bin / bin文件夾中刪除沒必要要的文件,如phpdebug,以減小壓縮包的大小。 有關如何建立部署包的更多詳細信息,請參閱文檔。
其實,使用Lambda運行PHP的原理很簡單,Lambda自己不原生支持PHP,但其實Lambda的背後也是一臺Linux的Instance。那麼你要作的就是,用一臺和Lambda運行環境同樣的機器來編譯PHP可執行文件,它能夠執行PHP代碼,而後在你的Lambda項目中包含這個PHP可執行文件。而後再以node.js爲入口,啓動PHP可執行文件,這個可執行文件會運行你指定的PHP腳本。在node.js的包裝器中,將Lambda參數傳遞給標準輸入,並等待標準輸出的結果,獲得結果後,將其做爲Lambda的運行結果返回。 而在這個過程當中PHP代碼會等待標準輸入,處理,並將結果輸出到標準輸出。
原文還寫了如何運行Go和Ruby在方法,由於跟運行PHP方式大同小異,因此在此就不作翻譯,感興趣的讀者請閱讀原文。