目录
创建Cosmos数据库帐户
使用输出绑定插入
修复我们的TypeScript
使用输入绑定读取
修复我们的发布
部署基础设施
部署Cosmos DB
部署DTAP
下一步
在本系列的第二部分中,我们使用默认的Visual Studio Code模板在Node.js和TypeScript中创建了一个Azure函数。我们还创建了一个构建管道来构建和测试代码并将TypeScript转换为JavaScript。通过发布管道,我们自动将功能部署到Azure。
在本文中,我们将向我们的函数添加一个数据库,然后将我们的函数(包括所需的基础设施)部署到开发、测试、验收和生产 (DTAP)。在本文结束时,我们将创建一个微服务,并带有一个数据库,可以部署到DTAP。
创建Cosmos数据库帐户让我们从在我们的函数中添加一个数据库开始。我们将Azure Cosmos DB与SQL API结合使用。我们有充分的理由使用SQL API,稍后您会看到。对于JavaScript或TypeScript开发人员,使用MongoDB API可能是有意义的。这意味着,尽管我们正在运行Cosmos DB,但我们可以使用任何MongoDB库(例如Mongoose)连接到它。但是,对于我们接下来向您展示的内容,SQL API将完成。
转到Azure门户并查找Cosmos DB。将它放在与您的函数相同的资源组中,以便以后轻松清理。选择一个独特的名称和您附近的地区。除此之外,保留所有默认设置。
创建可能需要几分钟,在我们的例子中是14分钟。同时,我们可以专注于我们函数的代码。
使用输出绑定插入为了从Cosmos DB中获取数据,我们使用Azure函数绑定。例如,如果我们将输入参数绑定到MongoDB查询,我们将自动获取一条记录。同样,我们可以添加一个输出绑定来返回一个对象,它会自动添加到Cosmos DB中。有不同的绑定,例如Blob、表和队列存储、服务总线和事件中心,但我们将使用Cosmos DB绑定。
您的函数在您的项目中有自己的文件夹,该文件夹包含一个function.json文件。当您打开此文件时,您会看到两个绑定,“输入”和“输出”绑定。这实际上是您的HTTP触发请求和响应。您还将看到您的函数当前允许使用GET和POST方法。
让我们从将文档插入我们的数据库开始。为此,我们将只使用POST,因此从配置中删除GET方法。为我们的函数添加一个路由也很好,使我们能够在以后添加其他函数。因此,将值为“person”的路由属性添加到输入绑定。此外,向您的配置添加额外的输出绑定。
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"post"
],
"route": "person"
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"name": "personOut",
"databaseName": "mydb",
"collectionName": "person",
"createIfNotExists": true,
"connectionStringSetting": "CosmosDBConnString",
"partitionKey": "/partitionKey",
"direction": "out",
"type": "cosmosDB"
}
],
"scriptFile": "../dist/HttpTrigger1/index.js"
}
Cosmos DB使用分区键对数据进行分区。该字段是必填字段,但您可以将其留空或使用常量字符串值。我们使用一个人的姓名首字母作为分区键。我们需要在这里指定分区键,因为我们告诉我们的函数创建数据库和集合,如果它们不存在。
此外,转到您的local.settings.json文件并添加CosmosDBConnString设置。在Cosmos DB帐户的密钥选项卡中的Azure门户中查找连接字符串。
修复我们的TypeScript我们现在可以更改我们的函数,使其返回到运行时。对于此人的ID,我们将使用GUID,因此首先运行npm install guid-typescript。 然后,添加import { Guid } from "guid-typescript";到TypeScript文件的顶部。
对于人,我们定义了一个接口。
interface Person {
id: string,
email: string;
partitionKey: string;
firstName: string;
lastName: string;
}
然后,在我们的函数中,我们创建一个人并将其添加到上下文绑定中,以便函数运行时知道它应该将此人添加到Cosmos DB。我们用:
context.bindings.[name you entered in your out binding configuration]
最后,我们将这个人返回给调用者,以便他们可以存储生成的ID。
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise {
let p: Person = {
id: Guid.create().toString(),
email: req.body.email,
partitionKey: req.body.firstName[0],
firstName: req.body.firstName,
lastName: req.body.lastName,
};
context.bindings.personOut = p;
context.res = {
// status: 200, /* Defaults to 200 */
body: p
};
};
现在,启动Postman或cURL或任何其他工具,使您能够向HTTP服务发出POST请求。启动您的函数并将URL(应该类似于https://localhost[:port]/api/person)复制到您选择的工具。然后,然后给它一个像这样的身体:
{
"email": "john.smith@contoso.com",
"firstName": "John",
"lastName": "Smith"
}
如果一切顺利,它应该返回200状态和您的人的副本。由于我们不验证John Smith是否已经存在,我们可以继续添加John Smith,但我们每次都应该获得一个唯一的ID。
通过在Azure门户中查找Cosmos DB帐户并转到数据资源管理器选项卡来确认它确实有效。
使用输入绑定读取现在,创建第二个函数以从Cosmos DB读取人员。在VS Code中,转到Azure选项卡,单击创建函数并选择HTTP触发器。这将在单独的文件夹中创建HttpTrigger2。
再次打开function.json文件,但这次删除POST方法并添加一个值为person/{partitionKey}/{id}的路由。Cosmos DB输入绑定看起来有点像输出绑定,只是我们需要指定ID和分区键。我们在这里使用我们的路由参数。
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get"
],
"route": "person/{partitionKey}/{id}"
},
{
"name": "personIn",
"databaseName": "mydb",
"collectionName": "person",
"connectionStringSetting": "CosmosDBConnString",
"id": "{id}",
"partitionKey": "{partitionKey}",
"direction": "in",
"type": "cosmosDB"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
],
"scriptFile": "../dist/HttpTrigger2/index.js"
}
这一次,我们可以从context.bindings.[name of the binding]中读取这个人。分区键和ID取自您的URL,因此我们可以通过浏览到https://[your URL]/api/person/[initial]/[ID]来获取一个人。TypeScript非常简单。
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise {
context.res = {
// status: 200, /* Defaults to 200 */
body: context.bindings.personIn
};
};
因此,无需为Cosmos DB编写任何代码,我们就能够在数据库中插入和读取文本。
修复我们的发布不幸的是,此更改破坏了我们的发布。如果您推送您的更改,您会看到一切都已发布并且似乎可以正常工作,直到您实际向URL发出请求。
这是因为local.settings.json文件不在源代码管理中,但我们向其中添加了连接字符串。要确认这确实是您的问题,请转到Azure门户中的Function App,然后转到“配置”并添加“CosmosDBConnString”和您的连接字符串作为值。该应用程序将重新启动,它应该会再次运行。
我们实际上可以将此解决方案添加到我们的版本中。在Azure DevOps发布管道中,将其添加到部署Azure Function App任务。
在任务中,找到App Settings然后添加-CosmosDBConnString $(CosmosDBConnString)。
现在,添加CosmosDBConnString变量并设置值,将范围设置为开发,并通过单击锁将其设为机密。连接字符串将添加到您的函数应用程序中,并且没有人能够看到该值(他们只能设置一个新值)。通过创建新版本来确认它有效。
部署基础设施现在一切正常。如果您对TypeScript进行更改并将其推送到您的存储库,它将被自动构建、测试和部署。但是,如果我们要创建另一个环境,则必须手动创建一个Function App和一个Cosmos DB,这既耗时又容易出错。
我们可以使用Azure资源管理模板(也称为 ARM 模板)、PowerShell、PowerShell Core、Bash或Shell在Azure中创建资源。向管道添加新任务并查找Azure CLI任务。将它放在Azure Functions任务之前。设置连接并选择脚本类型Shell和位置内联脚本。
我们现在可以将Azure CLI命令添加到我们的构建中。您可能希望将一些脚本添加到您的存储库并使用它们,但为简单起见,我们使用内联脚本。
我们先创建一个资源组,然后我们可以添加Function App,它也需要一个存储帐户。
az group create --name $(ResourceGroupName) --location $(Location)
az storage account create --resource-group $(ResourceGroupName) --name $(StorageAccountName) --location $(Location) --sku Standard_LRS
az functionapp create --resource-group $(ResourceGroupName) --name $(AppServiceName) --storage-account $(StorageAccountName) --consumption-plan-location $(Location) --functions-version 3 --os-type Linux --runtime node
现在,进入变量并添加ResourceGroupName、Location和StorageAccountName。将位置设置为“westeurope”或“westus”或您附近的任何内容。
您可以使用资源组的名称作为ResourceGroupName或使用新的名称,最好以“-dev”结尾,以便您知道这是您的开发环境。如果为资源组使用其他名称,则还必须为函数应用使用新名称,为存储帐户使用新名称。
存储帐户名称在所有Azure中必须是唯一的,只能包含字母,并且不得超过24个字符。这是一个严格的命名策略,但这就是Azure的工作方式。
确保除位置外的所有变量都适用于开发。填写完空格后,保存并运行部署并检查您是否没有收到错误。此部署可能需要几分钟时间,因为它会在您的Azure帐户中创建新资源。
部署Cosmos DB如果一切顺利,请将另一个Azure CLI任务添加到管道中,并将其放在Azure Functions任务之后。在此CLI中,我们将创建Cosmos DB帐户,读取连接字符串,并将其放置在应用服务的配置中。如果我们一直手动添加连接字符串,我们需要做一次发布,手动获取和设置连接字符串,最后再做一次发布。但是,我们希望这一切同时生效。
az cosmosdb create --resource-group $(ResourceGroupName) --name $(CosmosDBAccountName) --locations regionName=$(Location) failoverPriority=0 isZoneRedundant=False
CONN_STRING=$(az cosmosdb keys list --name $(CosmosDBAccountName) --resource-group $(ResourceGroupName) --type connection-strings --query "connectionStrings[0].connectionString" -o tsv)
az webapp config appsettings set --resource-group $(ResourceGroupName) --name $(AppServiceName) --settings "CosmosDBConnString=$CONN_STRING"
Cosmos DB成功部署后,查询连接字符串并将其存储在脚本变量中。最后,添加CosmosDBConnString到我们的函数应用程序的配置中。通过在脚本中执行此操作,我们可以部署我们想要的任何内容、更改名称、更改环境等等,并且我们将始终拥有连接字符串。
现在可以从Azure Functions任务和变量中删除连接字符串。
部署DTAP现在,转到您的管道概览,您可以在其中查看工件和阶段。将鼠标悬停在您的开发阶段,然后单击出现的克隆按钮。这将创建阶段“开发副本”,您可以将其重命名为“测试”。两个阶段之间有一条线,这意味着测试将在开发之后部署。单击测试阶段上的闪电按钮将触发器更改为仅手动。这将阻止您的代码在推送到您的存储库后自动进入您的测试环境。如果需要,您可以设置部署前批准。如果您进行了大量推送,但又不想在测试人员进行测试时打扰他们,则您可能更喜欢手动方法。
所以,很酷的是,你的整个开发阶段都被复制了,包括你的变量。但是,您的变量现在设置为测试范围。这意味着您只需要更改这些变量,就可以部署一个全新的环境!
由于我们没有在脚本中使用任何硬命名,我们甚至不必查看它们。因此,在您的变量中,在作用域为Test的变量上输入一个新名称。只有您的位置保持不变,因为它的作用域是整个版本。
设置变量后,保存,创建新版本,触发测试阶段,然后转到Azure门户以确认一切正常。尝试使用Postman触发您的Azure函数来插入和读取一个人。
下一步在本文中,我们向Azure函数添加了Cosmos DB输入和输出绑定。当然,您可以像往常一样使用npm包连接到任何数据库。通过将我们的基础设施添加到上一篇文章的发布管道中,我们能够快速轻松地启动新环境,无需人工干预,也无需追踪错误。
正如您在本系列中学到的,通过一些设置,您可以自动执行以前手动执行的任务。这让您有时间专注于更重要的项目,例如创建新功能来让您的客户惊叹,同时根据需要轻松扩展以支持您不断增长的客户群。
恭喜!完成本教程后,您现在正式成为云原生。如果您准备了解更多信息,请查看以您在此处开发的技能为基础的中级云原生系列。
要了解有关在Azure上使用Kubernetes的更多信息,请浏览Kubernetes Bundle | Microsoft Azure和Azure上的动手Kubernetes | 微软Azure。
Build a Complete Microservice - CodeProject