Serverless 物联网架构示例:基于 AWS 与 Alexa Skill

在 Dockercon 闭幕式上,我通过我的功能即服务(FaaS)项目展示了一系列 Serverless 演示。 在这篇文章中,我将谈谈我使用 Go 语言写的 Alexa 技能之一,以便在会议期间收集的数据。

步骤1:项目介绍

Docker 年度会议的闭幕会议是 Moby 的 Cool Hacks,这是一个比较优秀项目的展示。

每天,我们看到在 Docker 之上构建的很棒的新应用程序。然而,总是有一些不仅仅是为了酷炫的应用程序,而是在推动您可以用 Docker 做什么的界限。——引自 Mano Marks 的博客

一旦确认了我的 Cool Hack 项目将成为比赛获胜者之一,我设定了将我的演示与会议相关联的方法。Docker 的社区营销主管 Victor Coisne 告诉我有关 MobyMingle 的一个程序,让人们可以在活动中安排聚会、分享知识和结交新朋友。

我联系了 MobyMingle 所在的团队 E-180,在几周之内,他们向我展示了一个 API,从而可以从 MobyMingle 程序中获取统计信息。

我将谈谈我如何将 MobyMingle 与 Alexa 集成,为 Dockercon 演示产生一个有趣的演示。

相关的 keynote 视频:https://www.youtube.com/watch?v=-h2VTE9WnZs

步骤2:构建 Alexa Skill

Alexa 是去年早些时候 Amazon 在英国推出的语音助手。在写这篇文章的时候,有两个 “Alexa” 设备时:Echo 和 Echo Dot 可用。对于我的演示,我使用了一个 Echo dot。

为了向您的 Alexa 中添加自定义代码,您必须新建一个涉及三件事情的新技能:

  • 语音命令(示例语句)
  • 语音模式(意图和参数)
  • AWS Lambda 功能或公开可用的 HTTPS 结点

注意:因为安全原因,Amazon 不允许使用 HTTP 协议的 API 结点

示例语句

CountBrainDatesIntent      how many mingles have we had
CountBrainDatesIntent      how many mingles we had
CountBrainDatesIntent      how many mingles we had at dockercon
CountBrainDatesIntent      how many mingles were there
FindPopularKeywordIntent   what was the most popular keyword
FindPopularKeywordIntent   what was popular at dockercon

在左边,我们有 “Intent”(意图),在右边,我们可以定义任意数量的对应的语音命令。

与常规的图形用户界面(如网页)不同,它们通常有多种方法来做某事。用户体验(UX)与应用程序和网站一样适用于语音。

Intent Schema

在这里我们定义可用的 Intent,有一些由 Amazon 默认提供的,用于诸如 “help” 和 “what can i say” 之类的语句:

{
  "intents": [
    {
      "intent": "CountBrainDatesIntent"
    },
    {
      "intent": "FindPopularKeywordIntent"
    },
    {
      "intent": "AMAZON.HelpIntent"
    }
  ]
}

在这个例子中,没有一个 Intent 采用一个会让它们变得更容易使用的参数。有关参数 Intent 的示例,可以请点击此处 查看我的 Payroll Skill(myassistant)。

处理

然后,我们必须提供一个处理相应请求的应用程序。所有 Alexa 请求都使用 JSON 作为数据格式发送,具有 Intent 和所有的参数。他们预期一个 JSON 响应及你的 Echo 应该说出来的文本。

示例 JSON

我发现维护其中的几个在开发过程中测试处理程序,然后重新部署它是有用的。这是一个请求和响应的示例。

{
  "session": {
    "sessionId": "SessionId.9c5371aa-4b81-4810-b488-b4a83226a646",
    "application": {
      "applicationId": "amzn1.ask.skill.7314a604-a016-4d25-be3f-70447278c95d"
    },
    "attributes": {},
    "user": {
      "userId": "amzn1.ask.account.AF5LH4MBKILABA3WOTZA35OAIYD3NC3DYM3X64XJILWCYCSQ5IEDQYNKWSUQ7QGM4IM5TO3FQOUZQFSJZZMA2PZ37OBK4IRIN3CO5S53TXPGGBYN7OWFGRDRBESWJIU7NVWCQHECCJAJTODZHIMKZC445OCSXXV5RX3VB67HKNVTVWAL7CCRBMRS5ZBLRA3WF2F5FRIEEOA5XRA"
    },
    "new": true
  },
  "request": {
    "type": "IntentRequest",
    "requestId": "EdwRequestId.079b0a50-08ae-4d42-86f1-d8cbf09949c8",
    "locale": "en-GB",
    "timestamp": "2017-04-03T18:22:36Z",
    "intent": {
      "name": "FindPopularKeywordIntent",
      "slots": {}
    }
  },
  "version": "1.0"
}

响应示例:

{
  "version": "1.0",
  "response": {
    "outputSpeech": {
      "type": "PlainText",
      "text": "Moby says"
    },
    "card": {
      "content": "Moby says",
      "title": "Moby",
      "type": "Simple"
    },
    "shouldEndSession": true
  },
  "sessionAttributes": {}
}

我的 Golang 代码分布在三个文件上,不过它们都比较简单。

types.go

在解析 JSON 请求和构造 JSON 响应时,有许多 struct 类型可用于拆封/封送处理。

proxy.go

该文件用于抽象与 MobyMingle(E-180)服务的所有通信,因为一旦修改的时候,我们只需要修改一个地方。

以下是它包含的两个功能:

func getKeywordResponse() *BraindateTopicResponse
func getMingleResponse() *BraindateResponse

这些 URL 是硬编码的,但需要一个用于验证的访问令牌。我通过一个环境变量 access_token 传入。如果时间充足,Swarm 的 secret 将是一个更好的选择。

handler.go

这是 Alexa 技能的粘合剂。所有的 FaaS 功能通过读取 stdin 的请求,并将其响应写回到 stdout 来运行,这意味着 FaaS 功能不需要重复的样板代码。开箱即用,可以免费处理网络请求。

您可以在 GitHub 代码库中找到所有的代码,但这可能是最有趣的部分。在这里,我们告诉 Alexa 该回复的内容:

func buildOutput(intent *AlexaIntent) string {  
    var speech string
    if intent.Name == findPopularKeywordIntent {
        keywords := getKeywords()
        speech = "The most popular keywords were: " + strings.Join(keywords, " and ")
    } else if intent.Name == countBrainDatesIntent {
        brainDates := getBraindates()
        speech = fmt.Sprintf("We've had a total of %d mingles so far", brainDates)
    } else if intent.Name == AmazonHelp {
                speech = "You can say: what was the most popular keyword. And how many mingles have we had?"
        } else {
        speech = fmt.Sprintf("You wanted the %s intent, but I can't help you with that.", intent.Name)
    }
    return speech
}

支持具有 Alexa 技能的边缘案例(edge-cases)非常重要,否则您的用户将收到一个模糊的错误消息。在上面的代码中,我已经确定未预期的 Intent 处理得很好,还有 AmazonHelp 的短语(可以说什么?)。

步骤3:构建 FaaS 函数

FaaS 函数打包在 Docker 容器中。任何进程都可以是 FaaS 函数,如果它与 stdinstdout 一起使用。这意味着,即使是 UNIX 内置实用程序也可以是 Serverless 功能。

我的 Dockercon 演示使用两个独立的 Dockerfiles 来生成一个小型 FaaS 容器伴你。如果您现在要设置该任务,您可以利用多阶段构建,并使用单个 Dockerfile 来实现相同的结果。

Dockerfile.build 文件如下所示:

FROM golang:1.7.5
RUN mkdir -p /go/src/app
RUN go get github.com/alexellis/faas/watchdog/types
WORKDIR /go/src/app

COPY main.go .
COPY handler.go .
COPY types.go .
COPY proxy.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

CMD ["echo"]

Dockerfile 文件如下:

FROM alpine:latest
RUN apk add --no-cache ca-certificates

WORKDIR /root/

EXPOSE 8080
ENV http_proxy      ""
ENV https_proxy     ""

ADD https://github.com/alexellis/faas/releases/download/v0.5-alpha/fwatchdog /usr/bin
RUN chmod +x /usr/bin/fwatchdog
# COPY fwatchdog  /usr/bin/

COPY app    .

ENV fprocess="/root/app"
CMD ["fwatchdog"]

三行代码用于将普通的 Docker 容器放入 FaaS 函数中。以下是一个示例,你可以在 Docker hub 中添加 alpine:3.5 镜像来创建 echo function

ADD https://github.com/alexellis/faas/releases/download/0.5.5/fwatchdog /usr/bin

ENV fprocess="/bin/cat"

CMD ["fwatchdog"]

watchdog(看门狗) 位于 API 网关和您的代码之间,并处理所有的 HTTP 通信,因此您的代码就不需要处理。fprocess 变量指示 watchdog 为每个 HTTP 请求运行什么进程。

将我的 FaaS 项目运行在 AWS Lambda 的优点之一是,您可以使用任何您想要的编程语言编写代码,并在可用的任何硬件上运行。

这里有几个例子:

  • 你听说过 COBOL 吗? 也许你写了一些,或有一个亲戚做了。那么你可以在 COBOL 中编写这种函数
  • FaaS 也可以在 Raspberry Pi 上运行 - 也许您对 IoT 感兴趣或想在家中的低功耗服务器上运行代码?
  • 需要运行 Windows 本机可执行文件?这在混合操作系统 Docker Swarm 中得到了支持。

一步步的示例也可以在:OpenFaaS - TestDrive 中看到。

步骤4:结合

我希望这个玩法给你一个,如何将 Alexa 技能融合在一起的真实世界。

原文链接:https://blog.alexellis.io/serverless-alexa-skill-mobymingle/

尚未评分
您的评分将帮助我们做出更好的玩法

观光\评论区

Copyright © 2017 玩点什么. All Rights Reserved.