本文來自Mobingi官方技術專欄榄棵,歡迎關注
本文翻譯自Scripting Languages for AWS Lambda: Running PHP, Ruby, and Go
備注:Go已經在2018/01/15成為了AWS Lambda原生支持的語言,你可以從這里了解到更多信息https://aws.amazon.com/blogs/compute/announcing-go-support-for-aws-lambda/
在與合作伙伴與顧客一起的日常工作中,我們看到過很多不同領域婶芭、不同尋常的專業(yè)技能和經驗皮服,以及很多不同的編程語言楞艾。這些語言有些很老舊,而有一些非常前沿龄广,很多團隊都對它們的其中之一專研頗深硫眯,他們很可能想,在AWS上的新組件择同,比如AWS Lambda上也使用這些語言两入。
Lambda本身對很多語言提供原生支持,例如Java敲才、Node.js裹纳、Python和C#。在這篇文章中我們想描述如何在Lambda中使用其他的腳本語言(非原生支持的)紧武。
對于每一個你想要使用的語言剃氧,你需要完成下面的任務:
準備: 從AMI啟動一個實例,然后用SSH登陸阻星。
編譯: 打包你要在Lambda使用的語言
安裝: 創(chuàng)建Lambda包并測試代碼運行
每個編程語言的準備和安裝步驟基本相同朋鞍,所以我們在這里只提供PHP、Go、和Ruby的滥酥,一步一步編譯打包的例子更舞。
準備開始前共通步驟
Lambda允許你在Lambda運行環(huán)境中執(zhí)行任何可執(zhí)行文件。下面的步驟只是一個如何運行PHP坎吻、Go缆蝉、Ruby在Lambda上面的大框。不管怎么說瘦真,你還是可以用這個方法返奉,添加一些特定的庫,擴展編譯范圍吗氏,使用JSON將你的Lambda函數和Amazon API Gateway或者其它服務互聯(lián)。
在編譯好二級制文件雷逆,并設定好基礎文件結構之后弦讽,你就不需要再新建項目或者修改代碼的時候重復做這些步驟。只需要簡單編寫代碼接受STDIN的標準輸入膀哲,然后輸出結果到標準輸出STDOUT往产,寫好的Node.js包裝器將會負責連接你的輸入輸出到運行環(huán)境。
為了簡單起見某宪,我們僅演示準備PHP的步驟仿村,但這些步驟同樣適用于后面描述的其他運行環(huán)境。
在EC2控制臺兴喂,選擇Lanch instance蔼囊,選擇AMI時,請使用在Lambda Execution Environment and Available Libraries中的一個AMI衣迷,請設定你想要運行PHP代碼和啟動EC2的區(qū)域畏鼓。有關更多信息,請參閱Step 1: Launch an Instance壶谒。
選擇t2.large實例類型云矫,它具有兩個內核和8 GB內存,可以縮短PHP編譯時間汗菜。
選擇Review and Launch让禀,使用存儲的默認值,并且把實例加入到一個只開放SSH訪問的由向導生成的安全組中陨界。
選擇Launch繼續(xù);在啟動對話框中巡揍,您可以為登錄選擇現有的密鑰對值,也可以創(chuàng)建一個新的密鑰對值普碎。在這個例子中吼肥,我們創(chuàng)建一個名為php
的新密鑰對并下載它。
下載密鑰后,命令行進入到文件所在的文件夾并運行以下命令:
chmod 400 php.pem
基于SSH的安全標準缀皱,我們必須修改秘鑰權限《氛猓現在可以使用EC2的公共DNS連接到實例。在控制臺中選擇實例并在屏幕右下方的公共DNS下查找實例啤斗,獲得地址表箭。
ssh -i php.pem ec2-user@[PUBLIC DNS]
當實例啟動并運行后,你就在一個適當的區(qū)域中有了一個適當AMI钮莲,你可以用上面的命令登陸實例免钻,繼續(xù)執(zhí)行其他步驟。
準備PHP運行環(huán)境
登錄到正在運行的AMI后崔拥,你可以從源代碼編譯PHP7環(huán)境极舔,并準備好為Lambda環(huán)境打包。
給實例配置PHP
下一步是編譯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所在的區(qū)域選擇自己的鏡像洋闽。
cd ~
wget http://ie1.php.net/distributions/php-7.0.7.tar.bz2 .
使用以下命令提取文件:
tar -jxvf php-7.0.7.tar.bz2
上面的命令在你的home目錄中創(chuàng)建php-7.0.7文件夾,然后通過下面的命令突梦,創(chuàng)建一個專用的php-7二進制文件喊递。
mkdir /home/ec2-user/php-7-bin
cd php-7.0.7
./configure --prefix=/home/ec2-user/php-7-bin/
這可以確保PHP編譯很好地打包到您在home目錄中創(chuàng)建的指定PHP文件夾中。請記住阳似,我們只在此處編譯最基本PHP以減少Lambda函數的依賴骚勘。
你可以使用./configure中提供的選項為Lambda中PHP二進制文件加入更多依賴項或者編譯器選項。 運行./configure -h可以獲取有關可以打包到PHP發(fā)行版中的內容的更多信息撮奏。但請記住俏讹,這將增加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
代碼時間
使用你最喜歡的編輯器梯浪,創(chuàng)建一個入口PHP文件,在這個例子中瓢娜,我們從Linux管道讀取輸入挂洛,獲取一個簡單的JSON文檔,并計算此JSON數據的頂層節(jié)點數量眠砾,將結果輸出stdout虏劲。
<?php
$data = stream_get_contents(STDIN);
$json = json_decode($data, true);
$result = json_encode(array('result' => count($json)));
echo $result."\n";
?>
創(chuàng)建Lambda包
既然PHP的編譯和準備已經就緒了,現在需要做的就是創(chuàng)建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
下一步是創(chuàng)建一個Node.js包裝器文件币狠。該文件接受Lambda調用的輸入,使用helloLambda.php作為參數調用PHP可執(zhí)行文件砾层,并通過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侨糟,以減少壓縮包的大小碍扔。 有關如何創(chuàng)建部署包的更多詳細信息,請參閱文檔秕重。
譯者總結
其實不同,使用Lambda運行PHP的原理很簡單,Lambda本身不原生支持PHP溶耘,但其實Lambda的背后也是一臺Linux的Instance二拐。那么你要做的就是,用一臺和Lambda運行環(huán)境一樣的機器來編譯PHP可執(zhí)行文件凳兵,它可以執(zhí)行PHP代碼百新,然后在你的Lambda項目中包含這個PHP可執(zhí)行文件。然后再以node.js為入口庐扫,啟動PHP可執(zhí)行文件饭望,這個可執(zhí)行文件會運行你指定的PHP腳本仗哨。在node.js的包裝器中,將Lambda參數傳遞給標準輸入铅辞,并等待標準輸出的結果厌漂,得到結果后,將其作為Lambda的運行結果返回巷挥。 而在這個過程中PHP代碼會等待標準輸入桩卵,處理,并將結果輸出到標準輸出倍宾。
原文還寫了如何運行Go和Ruby在方法雏节,因為跟運行PHP方式大同小異,所以在此就不做翻譯高职,感興趣的讀者請閱讀原文钩乍。