学习使用 JavaScript、CosmosDB 和 Slack 触发无服务器数据库
本文是#25DaysOfServerless活动的一部分。整个十二月,微软云技术倡导者每天都会发布新的挑战。了解更多关于 Microsoft Azure 如何助力您实现无服务器功能的信息。
有什么想法或解决方案吗?欢迎在推特上分享!
愿望大师2000
又到了一年一度的节日季。孩子们开始许愿,希望在圣诞袜里收到一份惊喜礼物。
为了让圣诞老人能把礼物送到每个孩子手中,他希望孩子们能给他写信。
他当然知道我们生活在2019年,互联网无处不在。收到数百万封手写信件的时代已经一去不复返了。他还希望每次收到新的愿望时,精灵们都能收到通知。
圣诞老人需要以下物品:
- 网页应该将请求发送到函数端点,以便存储愿望及其所有元数据。
- 用于存储愿望的函数端点,此端点应接收孩子的愿望并将其存储在 CosmosDB 数据库中。
- 这是一个由 CosmosDB 触发的函数端点,该端点应该对数据库中插入的每个新愿望做出反应,并向精灵们管理的 Slack 频道写入一条消息。
- 我们建了一个精灵专用的Slack群组,每次数据库里有了新内容,我们都想让精灵们知道,这样他们就不会偷懒了:)
让我们绘制出这个系统的架构图,以便对整个情况有一个宏观的了解:
参考
-
免费 Azure 帐户您需要在 Azure 上注册才能搭建 Cosmos DB 数据库并创建存储帐户
-
如何安装 Azure CLI?
在某些操作中,我们会使用终端中的 Azure CLI。这是管理资源的绝佳方式。 -
在 VS Code 中创建 Azure 函数,
本文将向您展示如何在 VS Code 中构建您的第一个 Azure 函数。 -
本文将引导您完成构建 Node.js 应用程序、创建 Azure Cosmos DB 应用程序以及将两者连接起来的过程。
-
使用 Azure CLI 创建 Azure Cosmos DB
本文演示了如何使用 Azure CLI 设置 Cosmos DB 数据库。 -
使用 Azure CLI 创建 Azure Cosmos DB 以及其他资源。
本文展示了在设置 Azure Cosmos DB 之前和期间可能需要创建的所有不同资源,内容比上面的链接略长一些。 -
使用 Azure Cosmos DB 客户端实现无服务器 CRUD 操作
这是我同事 Simona Cotin 的一个代码库,展示了如何使用 MongoDB 客户端执行完整的 CRUD 操作。 -
GitHub 上的 Serverless + Azure Cosmos DB 参考页面。
这是关于 Serverless + JavaScript + Azure Cosmos DB 组合的最完整页面。
网页
网页应该支持收集发布愿望所需的数据。那么,愿望都包含哪些内容呢?
- 愿望,愿望本身,这应该是一个更长的文字描述。
- 来自,这应该是写祝福的人的姓名,最好是姓名+地址。
好的,那么我们需要什么来构建这个网页呢?很容易想到我们需要一个单页应用(SPA)框架。为了证明并非如此,我将使用原生 JavaScript 来构建它,也就是不使用任何框架。为此,我需要以下文件:
-| /webpage
---| index.html
---| app.js
---| app.css
请确保您拥有类似这样的工具http-server,以便您可以轻松地在本地测试此网页。
index.html
这部分应该包含网页的标记。也就是说,需要包含用于接收用户请求的输入字段,以及将内容提交到目标端点的方式。
请将内容更改为以下内容:
<!-- index.html -->
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="app.css">
</head>
<body>
<div class="page">
<h2>Make wish</h2>
<div class="item">
<textarea rows="10" cols="70" placeholder="I wish..." name="wish" id="wish"></textarea>
</div>
<div class="item">
<input type="text" placeholder="From" name="from" id="from" />
</div>
<div class="item">
<button id="sendButton">
Send
</button>
</div>
</div>
<div class="item response" id="response">
</div>>
<script src="app.js"></script>
</body>
</html>
app.js
这应该能够连接所有事件,并向指定端点执行所需的 Web 请求。请添加以下内容:
// app.js
const sendEl = document.getElementById('sendButton');
const wishEl = document.getElementById('wish');
const fromEl = document.getElementById('from');
const responseEl = document.getElementById('response');
const baseUrl = 'http://localhost:7000';
sendEl.addEventListener('click', sendWish)
async function sendWish() {
console.log('send wish');
const res = await fetch(`${baseUrl}/wish`, {
method: 'POST',
body: JSON.stringify({
wish: wishEl.innerHTML,
from: fromEl.innerHTML
})
})
const json = await res.json();
console.log('response', json);
responseEl.innerHTML = json;
}
app.css
我们需要为它添加一些合适的样式。让我们添加以下 CSS 类:
.page {
background: darkmagenta;
color: white;
display: flex;
align-items: center;
padding: 20px;
flex-direction: column;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.page .item {
margin-top: 10px;
}
.page .item textarea {
width: 100%;
}
.page .item button {
font-size: 16px;
border: solid 1px darkorange;
padding: 5px 10px;
color: white;
background: orange;
}
.page .item .response {
font-style: italic;
}
试试看
http-server -p 8008让我们通过启动并运行我们的应用程序来看一下http://localhost:8080:
用于存储愿望的函数端点
接下来,我们需要一个端点,供上述网页发送请求。我们可以将其构建为一个函数应用。请确保已安装以下软件:
-
安装 Azure Functions Core 工具。请点击此处查看适用于您操作系统的安装说明。
准备好了吗?好的,我们走吧 :)
构建函数应用
这一步骤包括我们执行以下操作:
- 配置 CosmosDB 数据库,我们需要一个数据库来存储我们的请求。
- 搭建函数应用框架,这意味着创建函数应用、函数端点,并添加连接到我们刚刚创建的 CosmosDB 数据库所需的代码。
提供 CosmosDB 数据库
点击左上角的菜单,portal.azure.com然后选择出现的模板。+ Create a resourceAzure Cosmos DB
请填写相应字段:
资源创建完成后,我们需要进入该资源并选择菜单选项Data Explorer,New Container如下所示:
您将被要求填写以下字段:
- 数据库 ID,你可以随意命名,我选择命名为
WishDB - 吞吐量,将其值设为 1000。
- 容器 ID,也就是集合的名称。集合包含一个文档列表。每个文档都类似于表中的一行,表和集合本质上是相同的。给它起个名字。
Wishes - 分区键,分区键指定 Azure Cosmos DB 集合中的文档如何在逻辑数据分区之间分布。这到底是什么意思呢?这意味着此数据库可以在云端扩展。我们告诉它如何扩展,以及如何使用分片技术来实现扩展。请提供该值。
/id
搭建函数应用程序
让我们在 VS Code 中打开命令面板并输入Azure Functions: Create New Project:
选择 JavaScript,当系统询问第一个函数时,为其命名Wish并确保它由 HTTP 触发。接下来,将Wish/index.js代码更改为以下内容:
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
module.exports = async function (context, req) {
context.log('Entering function');
if (!req.body.wish || !req.body.from) {
context.res = {
status: 400,
body: "Please pass wish,from"
};
}
const {
wish,
from
} = req.body;
context.bindings.newWish = JSON.stringify({
id: uuidv4(),
wish,
from
})
context.done();
};
该函数uuidv4()会生成一个唯一的 ID,这在数据库中非常有用。我们导出的主函数本身,只是从请求体中提取出 `<request_body>`wish和`<request_body>`,并将它们赋值给 `<request_body> `。最后,我们调用 `<request_body>` 。这就是将此内容插入CosmosDB 数据库所需的全部步骤。fromcontext.bindings.newWishcontext.done()
我们还没完全完成。我们还需要做两件事:
- 连接到我们的数据库,我们通过
local.settings.json使用连接字符串进行更新来实现这一点。 - 安装 CosmosDB 所需的绑定,我们需要更新
host.json以安装对 CosmosDB 的绑定支持。
连接到我们的数据库
CosmosDB我们需要在属性Values中添加以下键local.settings.json。该属性的值应赋值为数据库的连接字符串信息,我们可以在portal.azure.com菜单选项Keys和字段中找到它PRIMARY CONNECTION STRING。
接下来,我们需要更新Wish/function.json并添加一个绑定,该绑定指向我们的CosmosDB键,local.settings.json同时也指向数据库名称、集合以及我们可以引用的名称引用。我们需要将以下绑定条目添加到bindings数组中function.json:
{
"name": "newWish",
"type": "cosmosDB",
"databaseName": "WishDB",
"collectionName": "Wishes",
"createIfNotExists": true,
"connectionStringSetting": "CosmosDB",
"direction": "out"
}
如上所示,我们指出了上述所有内容,以便连接到我们的数据源。此外,我们还指出了newWish我们在 . 中引用的命名引用Wish/index.js。
安装 CosmosDB 绑定
我们需要安装 CosmosDB 的绑定。这意味着我们需要一些库,以便我们的 JavaScript 代码能够与 CosmosDB 代码进行通信。打开host.json函数应用根目录下的文件,并添加以下内容:
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
}
}
下面这些值extensionBundle会强制 VS Code 在调试模式下安装所有需要的绑定。
在生产环境中,这样做可能有点过度。通常情况下,您只需要安装 CosmosDB 即可。一旦我找到只安装 CosmosDB 的方法,而不是像现在这样安装所有组件,我就会更新这篇教程。
CosmosDB 触发函数端点
该解决方案包含两部分:
- 当数据库中出现新行时,就会触发一个函数端点。当数据库中发生新的更改(例如新增一行)时,我们的函数端点将被调用。
- 通过与 Slack 集成,一旦我们的函数被调用,我们就能将刚刚在数据库中创建的数据获取出来,并将其发送到其他地方。这个其他地方就是 Slack。
函数端点
首先,我们将搭建函数终结点。我们可以使用 VS Code 中的 Azure 函数扩展,通过命令面板和相应选项轻松完成此操作Azure Function: Create function。给这个新函数命名NewWish,并确保它使用`<function_name>` 和 `<authorization>`JavaScript作为Anonymous授权(部署后,我们可以将其更改为 `<function_name>` 以提高安全性)。
NewWish/function.json
接下来,我们需要添加一个连接到 CosmosDB 数据库的外部function.json绑定。我们的NewWish目录应该包含以下内容:
{
"bindings": [
{
"type": "cosmosDBTrigger",
"name": "documents",
"direction": "in",
"connectionStringSetting": "CosmosDB",
"databaseName": "WishDB",
"collectionName": "Wishes",
"createLeaseCollectionIfNotExists": "true"
}
]
}
如您所见,我们赋予它以下值:
- 类型,其值为
cosmosDBTrigger,这将确保在向数据库添加新行时触发该函数。 - 名称,这是我们在代码中将要使用的名称。
- 方向必须正确
in,因为数据是传入的,我们正在读取它。 - connectionStringSetting,它指向一个名为 的内容
CosmosDB,这是我们需要设置的键。local.settings.json - databaseName,这是我们在创建数据库时为其指定的名称。
- collectionName,这是我们在创建它时赋予它的名称。
local.settings.json
如前所述,这需要一个名为 `ConnectionString` 的键CosmosDB,该键需要指向 Azure 门户中数据库资源的连接字符串。让我们从该local.setting.json文件开始:
"Values": {
"AzureWebJobsStorage": "<should point to connection string for a storage account>",
"FUNCTIONS_WORKER_RUNTIME": "node",
"CosmosDB": "<should point to connection string for your CosmosDB database>"
}
接下来,转到 Azure 门户中的资源,然后找到菜单选项Keys并复制其下的值PRIMARY CONNECTION STRING。至于存储帐户,我们暂时先不用管它,因为首次调试时系统会提示我们输入帐户。
NewWish/index.js
因为我们将使用该库node-fetch,所以首先在函数应用程序的根目录下运行以下命令:
npm install node-fetch
接下来,给index.js文件添加以下内容:
const fetch = require('node-fetch');
module.exports = async function (context, documents) {
if (!!documents && documents.length > 0) {
context.log('Document Id: ', documents[0].id);
// call slack
const [row] = documents;
fetch(
"<webhook URL at slack>",
{
method: "POST",
body: JSON.stringify({
text: `ID: ${row.id} FROM: ${row.from} WISH: ${row.wish}`
}),
headers: { "Content-Type": "application/json" }
}
);
}
}
当数据库收到新行时,会调用上述代码。新行存储在参数中。然后,我们会调用 Slack API并将documents信息发布到 `<app_name>`、`<app_name>`和 ` <app_name>` 上。不过,我们缺少 WebHook URL,接下来需要解决这个问题。IdFromWish
Slack WebHook
我们需要以下条件才能与 Slack 通信。
- 创建 Slack 工作区,请按照此指南创建工作区
- 创建 Webhook
- 创建一个 Slack 应用(如果你还没有的话)。
- 在设置页面启用传入 Webhook 。
- 点击“向工作区添加新的 webhook” 。
- 选择应用要发布内容的渠道,然后点击“授权”。
然后你应该会看到类似这样的页面:
按下按钮后Copy,我们现在应该就能得到所需的 WebHook URL,并且可以更新我们的fetch调用了NewWish/index.js。不如我们来试一试吧?
测试一下
为了验证这一点,我们需要执行以下操作:
- 要启动并运行该功能,我们通过选择来实现。
Debug/Start Debugging - 要添加新行,我们访问 portal.azure.com,找到我们的资源,然后向数据库中添加一个新条目。
- 查看 Slack 频道,我们的 Slack 频道现在应该包含端点
NewWish发送到 Slack 的已发布消息。
启动并运行该功能
我们进行选择Debug/Start Debugging,结果应该如下所示:
添加新行
通常情况下,我们会使用 Web 应用程序将数据插入数据库。但在这里,我们将采用更简单的方法,直接在 Azure 中访问数据库资源,选择菜单选项Data Explorer并单击New Item。之后,我们为其指定以下值:
{
"id": "some_id",
"from": "Chris",
"wish": "World peace"
}
然后点击Save。
首先,程序应该会在我们的 FunctionApp 中触发断点/NewWish,如下所示:
我们取消了断点,然后转到我们的 Slack 频道。
成功了!我们的数据库插入操作触发了函数应用的调用,该应用随后将消息发布到了 Slack 上。这下那些小精灵们可要小心了 ;)
概括
这真是一项不小的工程,涉及很多环节。但仔细想想,每个环节其实都很容易搭建,而且我们在连接 CosmosDB 的过程中也得到了很多帮助,这使得整个项目最终得以顺利完成。
你想提交你对这个挑战的解决方案吗?
想提交你的解决方案吗?请在本地构建解决方案,然后提交一个 issue。如果你的解决方案不涉及代码,你可以录制一段简短的视频,并在 issue 描述中附上链接。请务必告诉我们你的解决方案是针对哪个挑战的。我们非常期待看到你的作品!你有任何意见或问题吗?请在下方评论区留言。
整个十二月,我们将举办为期 25 天的无服务器架构挑战赛,敬请期待!请持续关注 dev.to,我们将在此发布挑战和解决方案!立即注册Azure 免费帐户,为挑战做好准备!
文章来源:https://dev.to/azure/learn-serverless-database-trigger-in-javascript-cosmosdb-slack-fm1









