通過Jets框架在AWS Lambda上實現無服務化Ruby

本文將構建一個SMS應用。爲了讓其更加有趣,本文將加入一些幽默元素。當用戶在應用中打字時,它將會回覆您一個由icanhazdadjoke API免費提供的笑話。該應用會展示如何上手Jets,以及創建控制器、動作和線路。我們將構建一個單端點,當某個號碼接收到SMS信息時,這個端點會對來自Twilio的HTTP請求做出反應。端點每次都會返回TwiML,以及一個隨機的、令人爆笑的笑話。

當AWS在2014年發佈Lambda時,沒有支持Ruby,而Python、Node.js和Java等平臺開始了針對雲託管和雲運行功能的無服務化革命。在2018年底,對Ruby的支持終於發佈。

開發者可以使用原始功能和無服務應用模型(SAM)模板,通過Ruby on Lambda構建任何東西,正如《Ruby on Lambda的開始指南》中描述的那樣。但是,Ruby的主要目的在於讓開發者更快樂,而不是更痛苦。因爲,當配置文件比程序還長時,整個流程可以說會讓人非常痛苦。Jets 框架是一個利用Ruby來讓無服務化更加快樂的框架。

從Rails過渡到Jets

Jets將構建Rails 應用體驗和部署AWS Lambda,並和相關服務能力加以結合。相關服務包括:API Gateway, S3和DynamoDB。在本帖中,我們將看看如何使用Jets並部署一個基於Lambda、用Ruby編寫的的Twilio應用。

我們構建的是什麼

爲了簡便,我們將要構建一個SMS應用。而且,爲了讓其更加有趣,我們還將加入一些幽默元素。當你在該應用中打字時,它將會回覆一個笑話,由icanhazdadjoke API免費提供。

這個應用會向我們展示如何上手Jets,以及如何創建控制器、動作和線路。我們將構建一個單端點,當某個號碼接收到SMS信息時,這個端點會對來自Twilio的HTTP請求做出反應。每次,這個端點會返回TwiML,以及一個隨機的、令人爆笑的笑話。

需要什麼

爲了完成這個項目,開發者需要準備:

開始

首先,全局安裝jets gem。在命令行中鍵入:

gem install jets

然後,Jets可執行文件就可以被當做生成器使用,如同Rails,用來發起一個新項目,並運行該項目中的命令。我們現在會創建一個新項目,但是鑑於本帖子的範圍有限,我們會對該項目適當進行限制。首先,我們將在API模式下創建項目,因爲在這個應用中,我們不需要HTML視圖。而且,我們也無需通過webpacker來進行資產編譯,所以,這會節省我們的構建時間。我們也不需要數據庫。運行以下命令,創建一個新的項目:

jets new dad-jokes-sms --mode api --no-database

在生成器完成運行後,切換到dad-jokes-sms目錄下,運行以下命令,以本地運行你的應用:

jets serve

打開http://localhost:8888,你會看到以下的頁面:

如果看到了這個頁面,說明新Jets項目運行成功。

第一個Jets控制器

現在已經有了Jets應用,因此可以使用gem來生成應用部件,從模型和控制器到完整架構。對於應用來說,需要只有一個動作的控制器。怎麼生成它呢?運行以下命令:

jets generate controller Messages create

生成器將創建和編輯一些文件。開發者需要檢查新的路徑,因此請打開config/routes.rb。

Jets生成了一個GET線路,但是Twilio webhook會默認生成POST請求,而我寧可讓它保持現在這樣。設置應用,使之在/messages端點上接收POST請求webhook,像這樣:

Jets.application.routes.draw do
 post 'messages', to: 'messages#create'
 root "jets/public#show"

jets/public#show 控制器可以提供來自公共文件夾的靜態utf8內容。注意,作爲部署流程的一部分,Jets會將公共文件夾下的文件上傳到s3中,並且從s3中直接提供這些文件。S3非常適合提供靜態資產。此處有更多信息: http://rubyonjets.com/docs/assets-serving/

 any "*catchall", to: "jets/public#show"
end

現在,讓我們編寫控制器的動作。打開app/controllers/messages_controller.rb,你會看到“創建”動作的方法。這一動作會接收Twilio webhook,並用TwiML進行回覆,且返回一個笑話。

獲取笑話

爲了返回笑話,我們需要對icanhazdadjoke API進行調用。讓我們快速寫一個能夠實現這一目標的私有方法。

我們將使用open-uri,因爲它在發送簡單的web請求方面(包括下載文具和圖片)十分有用。Jets生成了一個GET路徑,但是Twilio webhook會默認生成POST請求,而我寧可讓它保持這樣。在MessagesController中加入以下內容:

require 'open-uri'
class MessagesController < ApplicationController
 def create
 end
 private
 def random_joke
 open('https://icanhazdadjoke.com/', { 'Accept' => 'text/plain' }).read
 end
end

現在,可以將笑話以TwiML的形式返回給Twilio。

返回TwiML

我們將構建一個回覆,方法是使用來自twilio-ruby助手庫中的助手程序。打開Gemfile,添加twilio-ruby:

source "https://rubygems.org"
gem "jets"
gem "twilio-ruby"

在命令行中運行bundle install,以安裝gem。在create動作中,實例化一個新的TwiML回覆對象,使用 TwiML element來回復進來的消息,並提供XML回覆,方法如下:

require 'open-uri'
class MessagesController < ApplicationController
 def create
 twiml = Twilio::TwiML::MessagingResponse.new
 twiml.message body: random_joke
 render xml: twiml.to_xml
 end
 private
 def random_joke
 open('https://icanhazdadjoke.com/', { 'Accept' => 'text/plain' }).read
 end
end

要知道更多關於如何使用twilio-ruby助手庫來生成TwiML的信息,請閱讀文檔。
我們可以在本地運行以測試是否可得到預期回覆。如果應用停止,請運行jets serve重啓。使用curl向localhost:8888/messages發送POST請求,你便會在TwiML回覆中看到由icanhazdadjoke提供的笑話。

curl --data "" http://localhost:8888/messages
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Message>What’s the advantage of living in Switzerland? Well, the flag is a big plus.</Message>
</Response>

非常好,Jets開始工作了!現在我們要把它部署到AWS Lambda中。

要將Jets應用部署到AWS,首先需要設置好項目和證書,以便讓它可以訪問AWS服務。一個比較好的做法是創建擁有其工作所需最少權限的用戶,Jets文檔描述了用戶需要的最少權限。在AWS賬戶中創建一個策略,該策略包含所有這些權限。此外,還要創建一個新用戶,該策略將被分配給這個用戶。然後,就可以使用該用戶的證書來部署應用。

AWS 控制面板中,找到IAM服務,或者直接跳到IAM部分

跳轉到Policies部分,並創建一個新的策略。

選擇JSON選項卡,輸入來自Jets文檔的以下JSON:

{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "apigateway:*",
 "cloudformation:*",
 "dynamodb:*",
 "events:*",
 "iam:*",
 "lambda:*",
 "logs:*",
 "route53:*",
 "s3:*"
 ],
 "Resource": [
 "*"
 ]
 }
 ]
}

繼續點擊,檢查該策略,並命名。

保存策略。現在,需要創建一個新用戶,並且將策略添加給該用戶,並給予該用戶創建Jets需要部署的資源的權限。打開IAM控制面板中的Users部分,創建一個新用戶。

給該用戶命個名,再在Access Type中選擇Programmatic Access。

點擊Next,並選擇給予該新用戶的權限。選擇Attach existing policies directly,並篩選剛剛創建的策略。選擇該策略,並點擊Next。

點擊Next,直到成功頁面出現爲止。

保存最終頁面上顯示的Access key ID和Secret access key。在部署的時候,我們要用到它們。現在,我們已經做好部署準備。

在Lambda上進行部署

在命令行中輸入:

AWS_ACCESS_KEY_ID=YOUR_USER_KEY AWS_SECRET_ACCESS_KEY=YOUR_USER_SECRET_KEY jets deploy

Jets將把證書作爲環境變量來設置AWS賬戶中的所有資源,以方便應用運行。這會花費一些時間,但是完成後,你會得到一個URL,而且應用會在上面運行。

你會注意到應用被部署到一個“開發”環境中。要知道更多關於Jets如何處理環境的信息,請閱讀文檔。

現在可以用curl來測試這個URL。記住,我們使用了/messages這條線路,所以務必在API網關端點末端加上它,並且發出一個POST請求。

$ curl --data "" https://YOUR_API_GATEWAY_ENDPOINT/messages
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Message>I knew a guy who collected candy canes, they were all in mint condition</Message>
</Response>

現在,我們便可以隨時收到笑話了,讓我們把它與Twilio號碼連接起來。

通過SMS發送笑話

訪問Twilio 控制面板,轉到有效電話號碼。如果你已經有一個號碼,請編輯它,否則,請購買一個可以接收SMS信息的新號碼。在A message comes in字段中,輸入你的應用URL。

保存號碼,並向其發送一條信息,應該會在回覆中得到一個笑話。

無服務化有趣的事情

在本帖中,我們見證瞭如何使用Jets來編寫Ruby應用,並將它部署到AWS Lambda中。你可以在GitHub上看到完整的項目

Jets能幫助完成的東西遠不止這些,譬如:對事件作出反應將數據儲存到數據庫中,甚至是運行你現有的Rails應用等等。閱讀Jets文檔中的這些文章,瞭解更多Jets的功能。

查看英文原文:Serverless Ruby on AWS Lambda with the Jets framework

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章