通过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

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