Ở thời điểm hiện tại (22.04.2020) aws lambda không hỗ trợ mặc định các trương trình php trên hệ thống của họ, chỉ hỗ trợ các ngôn ngữ như python, nodejs …
nếu muốn sử dụng được code php trên lambda chúng ta phải tự build runtime của php lên để thực thi code của mình. Bài viết này mình sẽ hướng dẫn các bạn các thao tác cần thiết để chạy được code php trên mỗi trường lambda.
Build php runtime
Thực hiện các bước sau để build custom runtime php.
- Khởi tạo EC2 instance amzn-ami-hvm-2018.03.0.20181129-x86_64-gp2. chú ý các bạn bắt bược phải dùng instance của aws để thực hiện build runtime này, bạn không thể build được ở local hay bất kỳ một server nào khác, nếu build trên môi trường khác đưa vào lambda nó sẽ báo lỗi file.
- SSh vào server ec2 vừa tạo thực hiện các câu lệnh sau đây.
Cài các package cần thiết:123sudo yum update -ysudo yum install autoconf bison gcc gcc-c++ openssl-devel libcurl-devel libxml2-devel libjpeg-devel libpng-devel php-mysqlnd php-zip php-devel php-gd php-mcrypt php-mbstring php-curl php-xml php-pear php-bcmath php-json -y - Tiến hành Compiling PHP
- Tải PHP 7.3 source1234mkdir ~/php-7.3-bincurl -sL https://github.com/php/php-src/archive/php-7.3.0.tar.gz | tar -xvzcd php-src-php-7.3.0
- Compiling1234./buildconf --force./configure --prefix=/home/ec2-user/php-7.3-bin/ --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-openssl --with-openssl-dir=/usr/include/openssl --with-curl --with-zlib --enable-mbstring --with-gd --with-jpeg-dir=/usr/lib64make install
Thao tác build này diễn ra khá lâu, các bạn đợi chút nhé
Sau khi bạn thực hiện các công việc này xong, nó sẽ tạo ra một load các folder trong thưc mục /home/ec2-user/php-7.3-bin/ cho bạn, trong đó có 1 file php trong thư mục~/php-7.3-bin/bin/php
, đây chính là cái các bạn cần để chạy được php trên mỗi trường lambda. Đến đây bạn có thể download cái~/php-7.3-bin/bin/php
này về để thực hiện trên local của bạn. - Tải PHP 7.3 source
- Bước tiếp theo bạn tạo 1 thư mục có cấu trúc như sau:
1 2 3 4 5 6 7 8 9 10 | /home/ec2-user/php-example/ +-- bin/ | +-- php* # là cái php đã build được |-- bootstrap* # ngang hàng với thư mục bin và src +-- src/ +-- hello.php |-- composer.json # ngang hàng với thư mục bin và src có 2 folder, 4 files tất cả (tý sẽ có thêm folder vendor) |
Các file sẽ có nội dung như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | // file bootstrap #!/opt/bin/php <span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token comment">// require vendors from layer</span> <span class="token keyword">require</span> <span class="token constant">__DIR__</span><span class="token punctuation">.</span><span class="token single-quoted-string string">'/vendor/autoload.php'</span><span class="token punctuation">;</span> <span class="token comment">// require file with function basing on ENV configuration</span> <span class="token variable">$handlerFunction</span> <span class="token operator">=</span> <span class="token function">array_slice</span><span class="token punctuation">(</span><span class="token function">explode</span><span class="token punctuation">(</span><span class="token single-quoted-string string">'.'</span><span class="token punctuation">,</span> <span class="token variable">$_ENV</span><span class="token punctuation">[</span><span class="token single-quoted-string string">'_HANDLER'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">require_once</span> <span class="token variable">$_ENV</span><span class="token punctuation">[</span><span class="token single-quoted-string string">'LAMBDA_TASK_ROOT'</span><span class="token punctuation">]</span> <span class="token punctuation">.</span> <span class="token single-quoted-string string">'/src/'</span> <span class="token punctuation">.</span> <span class="token variable">$handlerFunction</span> <span class="token punctuation">.</span> <span class="token single-quoted-string string">'.php'</span><span class="token punctuation">;</span> <span class="token comment">// Generate random number to test Lambda Execution Context</span> <span class="token variable">$sharedRandom</span> <span class="token operator">=</span> <span class="token function">rand</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token variable">$client</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">GuzzleHttpClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$request</span> <span class="token operator">=</span> <span class="token function">getNextRequest</span><span class="token punctuation">(</span><span class="token variable">$client</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">try</span> <span class="token punctuation">{</span> <span class="token variable">$response</span> <span class="token operator">=</span> <span class="token variable">$handlerFunction</span><span class="token punctuation">(</span><span class="token variable">$request</span><span class="token punctuation">[</span><span class="token single-quoted-string string">'payload'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token variable">$sharedRandom</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Handle invocation error and notify Runtime API</span> <span class="token function">handleInvocationError</span><span class="token punctuation">(</span><span class="token variable">$client</span><span class="token punctuation">,</span> <span class="token variable">$request</span><span class="token punctuation">[</span><span class="token single-quoted-string string">'invocationId'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token variable">$e</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">sendResponse</span><span class="token punctuation">(</span><span class="token variable">$client</span><span class="token punctuation">,</span> <span class="token variable">$request</span><span class="token punctuation">[</span><span class="token single-quoted-string string">'invocationId'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token variable">$response</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">getNextRequest</span><span class="token punctuation">(</span><span class="token variable">$client</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">array</span> <span class="token punctuation">{</span> <span class="token variable">$response</span> <span class="token operator">=</span> <span class="token variable">$client</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token single-quoted-string string">'http://'</span><span class="token punctuation">.</span><span class="token variable">$_ENV</span><span class="token punctuation">[</span><span class="token single-quoted-string string">'AWS_LAMBDA_RUNTIME_API'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token single-quoted-string string">'/2018-06-01/runtime/invocation/next'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'invocationId'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token variable">$response</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">getHeader</span><span class="token punctuation">(</span><span class="token single-quoted-string string">'Lambda-Runtime-Aws-Request-Id'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token single-quoted-string string">'payload'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token function">json_decode</span><span class="token punctuation">(</span><span class="token punctuation">(</span>string<span class="token punctuation">)</span> <span class="token variable">$response</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">getBody</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">sendResponse</span><span class="token punctuation">(</span><span class="token variable">$client</span><span class="token punctuation">,</span> <span class="token variable">$invocationId</span><span class="token punctuation">,</span> <span class="token variable">$response</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$client</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">post</span><span class="token punctuation">(</span> <span class="token single-quoted-string string">'http://'</span> <span class="token punctuation">.</span> <span class="token variable">$_ENV</span><span class="token punctuation">[</span><span class="token single-quoted-string string">'AWS_LAMBDA_RUNTIME_API'</span><span class="token punctuation">]</span> <span class="token punctuation">.</span> <span class="token single-quoted-string string">'/2018-06-01/runtime/invocation/'</span> <span class="token punctuation">.</span> <span class="token variable">$invocationId</span> <span class="token punctuation">.</span> <span class="token single-quoted-string string">'/response'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token single-quoted-string string">'body'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token variable">$response</span><span class="token punctuation">]</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">handleInvocationError</span><span class="token punctuation">(</span><span class="token variable">$client</span><span class="token punctuation">,</span> <span class="token variable">$invocationId</span><span class="token punctuation">,</span> <span class="token package">Exception</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$client</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">post</span><span class="token punctuation">(</span> <span class="token single-quoted-string string">'http://'</span> <span class="token punctuation">.</span> <span class="token variable">$_ENV</span><span class="token punctuation">[</span><span class="token single-quoted-string string">'AWS_LAMBDA_RUNTIME_API'</span><span class="token punctuation">]</span> <span class="token punctuation">.</span> <span class="token single-quoted-string string">'/2018-06-01/runtime/invocation/'</span> <span class="token punctuation">.</span> <span class="token variable">$invocationId</span> <span class="token punctuation">.</span> <span class="token single-quoted-string string">'/error'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span> <span class="token single-quoted-string string">'body'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token function">json_encode</span><span class="token punctuation">(</span><span class="token punctuation">[</span> <span class="token single-quoted-string string">'errorType'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token single-quoted-string string">'CustomInvocationError'</span><span class="token punctuation">,</span> <span class="token single-quoted-string string">'errorMessage'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token variable">$e</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">getMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token single-quoted-string string">'stackTrace'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token variable">$e</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">getTraceAsString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token single-quoted-string string">'headers'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token punctuation">[</span> <span class="token double-quoted-string string">"Lambda-Runtime-Function-Error-Type"</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token double-quoted-string string">"Unhandled"</span> <span class="token punctuation">]</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </span> |
#composer.json
1 2 3 4 5 6 7 8 | <span class="token punctuation">{</span> <span class="token property">"require"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"guzzlehttp/guzzle"</span><span class="token operator">:</span> <span class="token string">"^6.3"</span><span class="token punctuation">,</span> <span class="token property">"aws/aws-sdk-php"</span><span class="token operator">:</span> <span class="token string">"^3.99"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
cuối cùng là hello.php
1 2 3 4 5 | <span class="token keyword">function</span> <span class="token function">hello</span><span class="token punctuation">(</span><span class="token variable">$data</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token double-quoted-string string">"Hello, <span class="token interpolation"><span class="token punctuation">{</span><span class="token variable">$data</span><span class="token punctuation">[</span><span class="token single-quoted-string string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">}</span></span>!"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
- Bạn vào thưc mục này để cài đặt nội dung tiếp theo
- Cài đặt composer, nhiều máy có rồi thì bỏ qua bước này12curl -sS http://getcomposer.org/installer | php
- Install dependencies12php composer.phar install
- Tạo zip file để deploy code1234zip -r runtime.zip bin/ bootstrapzip -r vendor.zip vendor/zip -r hello.zip src/*
mình giải thích cụ thể từng file zip này một chút:- cái runtime.zip chính là php runtime để cho lambda chạy được code php
- vendor.zip là các package của php như guzzlehttp, aws-sdk-php, bạn có thể thêm bất cứ package nào cho việc code vào đây.
- hello.zip chính là source của các bạn.
==> cái runtime và vendor mình sẽ upload nó vào phần layer của lambda, còn hellp.zip thì pload vào phần function.
Đến bước này nếu ai đã biết cách deploy lambda thì cũng có thể tự deploy được rồi, mình sẽ hướng dẫn tiếp các bạn mới deploy lambda sử dụng aws cli nhé.
- Đầu tiên bạn phải tạo role cho lambda function AWSLambdaBasicExecutionRole and S3FullAccess policies
- Configure AWS CLI tool
- Tạo layers
- Custom runtime layer12aws lambda publish-layer-version --layer-name php-custom-runtime --zip-file fileb://runtime.zip
- Layer with vendor12aws lambda publish-layer-version --layer-name php-custom-runtime-vendor --zip-file fileb://vendor.zip
- Custom runtime layer
sau khi chạy xong mỗi câu lệnh ở trên nó sẽ trả cho bạn một cái là version arn
các bạn lưu cái này lại để tạo function nhé:
- Create function12345678aws lambda create-function--function-name hello--zip-file fileb://hello.zip--handler hello--role "{ARN_OF_CREATED_ROLE}"--runtime provided--layers "{ARN_OF_RUNTIME_LAYER}" "{ARN_OF_VENDOR_LAYER}"
ok đến bước này là các bạn đã deploy xong fucntion lambda của mình rồi, bây giờ bạn cần login vào aws console để add trigger hoặc thực hiện thao tác add tương ứng.Tài liệu