练习 - 向函数应用添加逻辑
让我们继续介绍齿轮传动示例,并添加温度服务的逻辑。 具体而言,我们将从 HTTP 请求接收数据。
函数要求
首先,我们需要为逻辑定义一些要求:
- 从 0 到 25 度的温度应被标记为“正常”。
- 25 度以上至 50 度的温度应被标记为“警告”。
- 超过 50 度的温度应被标记为“危险”。
向函数应用添加一个函数
如之前单元中所述,Azure 提供了可帮助你生成函数的模板。 在本单元中,你将使用 HttpTrigger
模板来实现温度服务。
在上一个练习中,你部署了函数应用并打开了它。 如果它尚未打开,可从主页打开它,方法是选择“所有资源”,然后选择名为 escalator-functions-xxx 之类的函数应用。
在“函数应用”屏幕的“函数”选项卡下,选择“在 Azure 门户中创建”。 此时将显示“创建函数”窗格。
在“选择模板”下选择“HTTP 触发器”,然后选择“下一步”。
将“函数名称”保留为“HttpTrigger1”,将“授权级别”保留为“函数”,然后选择“创建”。 函数 HttpTrigger1 已创建并显示在 HttpTrigger1 函数窗格中。
选择“代码 + 测试”选项卡。代码编辑器随即打开,其中显示函数的 index.js 代码文件的内容。 以下代码片段中显示了 HTTP 模板生成的默认代码。
module.exports = async function (context, req) { context.log('JavaScript HTTP trigger function processed a request.'); const name = (req.query.name || (req.body && req.body.name)); const responseMessage = name ? "Hello, " + name + ". This HTTP triggered function executed successfully." : "This HTTP triggered function executed successfully. Pass a name on the query string or in the request body for a personalized response."; context.res = { // status: 200, /* Defaults to 200 */ body: responseMessage }; }
你的函数需要一个名称,才能通过 HTTP 请求查询字符串或作为请求正文的一部分进行传递。 函数通过返回消息“你好,<name>。此 HTTP 触发函数执行成功。”进行响应,回显在请求中发送的名称。
从源文件下拉列表中选择“function.json”以查看函数的配置(应类似于下面的代码)。
{ "bindings": [ { "authLevel": "function", "type": "httpTrigger", "direction": "in", "name": "req", "methods": [ "get", "post" ] }, { "type": "http", "direction": "out", "name": "res" } ] }
此配置文件声明的是该函数会在接收到 HTTP 请求时运行。 输出绑定声明的是该响应将作为 HTTP 响应发送。
在“模板详细信息”部分的“新建函数”字段中,输入“DriveGearTemperatureService”。 将“授权级别”保留为“函数”,然后选择“创建”以创建函数。 此时将显示 DriveGearTemperatureService 函数的“概述”窗格。
在“函数”菜单中,选择“代码 + 测试”。 此时会打开代码编辑器,其中显示 run.ps1 代码文件的内容。 以下代码片段中列出了模板为我们生成的默认代码。
using namespace System.Net # Input bindings are passed in via param block. param($Request, $TriggerMetadata) # Write to the Azure Functions log stream. Write-Host "PowerShell HTTP trigger function processed a request." # Interact with query parameters or the body of the request. $name = $Request.Query.Name if (-not $name) { $name = $Request.Body.Name } $body = "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response." if ($name) { $body = "Hello, $name. This HTTP triggered function executed successfully." } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = $body })
我们的函数需要一个名称,才能通过 HTTP 请求查询字符串或作为请求正文的一部分进行传递。 HTTP 函数必须通过写入其输出绑定生成响应,该绑定是使用
Push-OutputBinding
cmdlet 在 PowerShell 函数中实现的。 此函数会返回消息“Hello, $name”,回显请求中发送的名称。从源下拉列表选择“function.json”以查看函数的配置(应如下所示)。
{ "bindings": [ { "authLevel": "function", "type": "httpTrigger", "direction": "in", "name": "Request", "methods": [ "get", "post" ] }, { "type": "http", "direction": "out", "name": "Response" } ] }
此配置声明的是该函数会在接收到 HTTP 请求时运行。 输出绑定声明的是该响应将作为 HTTP 响应发送。
测试函数
提示
cURL 是一种命令行工具,可用于发送或接收文件。 它包含在 Linux、macOS 和 Windows 10 中,并可供大多数其他操作系统下载。 cURL 支持很多协议,如 HTTP、HTTPS、FTP、FTPS、SFTP、LDAP、TELNET、SMTP、POP3 等。 有关详细信息,请参阅以下链接:
若要测试函数,可以在命令行上使用 cURL 将 HTTP 请求发送至函数 URL。
展开触发器函数窗格底部的“日志”框架。 在日志框架顶部的下拉列表中选择“文件系统日志”。 日志框架应开始每分钟积累跟踪通知。
若要查找函数的终结点 URL,请在命令栏中选择“获取函数 URL”,如下图所示。 通过选择 URL 末尾的“复制到剪贴板”图标来保存此 URL。 将此链接存储到记事本或类似应用中,以备后用。
打开命令提示符并运行 cURL 以将 HTTP 请求发送到函数 URL。 请记住,请使用在上一步中复制的 URL。
curl "<your-https-url>"
提示
可能需要将 URL 括在引号中,以避免 URL 中出现特殊字符的问题。
如果使用的是 Windows,请通过命令提示符运行cURL
。 虽然 PowerShell 中有 curl 命令,但它是 Invoke-WebRequest 的别名,与cURL
并不同。响应应如下所示。
This HTTP triggered function executed successfully. Pass a name on the query string or in the request body for a personalized response.
现在,在请求中传递名称。 为此,需要将名为
name
的查询字符串参数添加到 URL。 以下示例添加了查询字符串参数name=Azure
。curl "<your-https-url>&name=Azure"
响应应如下所示。
Hello, Azure. This HTTP triggered function executed successfully.
函数已成功执行,并返回了在请求中传递的名称。
保护 HTTP 触发器
HTTP 触发器允许使用 API 密钥,通过要求每个请求都具备密钥来阻止未知的调用方。 在创建函数时,选择“授权级别”。 默认情况下,级别设置为“函数”,这需要特定于函数的 API 密钥。 也可将其设置为“管理员”以使用全局 master 密钥,或者将其设置为“匿名”以指示无需密钥。 还可以在创建函数后通过函数属性来更改授权级别。
由于在创建此函数时指定的授权级别是“函数”,所以需要在发送 HTTP 请求时提供密钥。 可以将它作为名为 code
的查询字符串参数发送。 或者,使用偏好的方法,将其作为名为 x-functions-key
的 HTTP 标头传递。
若要查找函数密钥,请在“概述”菜单的“函数”选项卡下选择函数名称(例如 HttpTriger1),以打开“代码 + 测试”菜单。 然后,选择“函数密钥”选项卡。
默认情况下,函数密钥值处于隐藏状态。 通过选择“显示值”来显示默认函数密钥值。 将“值”字段的内容复制到剪贴板,然后将此密钥存储在记事本或类似应用中供以后使用。
若要使用函数密钥测试函数,请打开命令提示符并运行 cURL 以向函数 URL 发送 HTTP 请求。 将
<your-function-key>
替换为保存的函数密钥值,并将<your-https-url>
替换为函数的 URL。curl --header "Content-Type: application/json" --header "x-functions-key: <your-function-key>" --request POST --data "{\"name\": \"Azure Function\"}" <your-https-url>
查看 cURL 命令并验证其是否具有以下值:
- 已添加
application/json
类型的Content-Type
标头值。 - 已将函数密钥作为标头值
x-functions-key
传递。 - 已使用
POST
请求。 - 使用函数的 URL 传递了 Azure 函数。
- 已添加
查看日志。
“代码 + 测试”窗格应打开一个显示日志文件输出的会话(确保在“日志”窗格顶部的下拉列表中选择了“文件系统日志”)。 日志文件根据请求状态进行更新,该状态应如下所示:
```output
2022-02-16T22:34:10.473 [Information] Executing 'Functions.HttpTrigger1' (Reason='This function was programmatically called via the host APIs.', Id=4f503b35-b944-455e-ba02-5205f9e8b47a)
2022-02-16T22:34:10.539 [Information] JavaScript HTTP trigger function processed a request.
2022-02-16T22:34:10.562 [Information] Executed 'Functions.HttpTrigger1' (Succeeded, Id=4f503b35-b944-455e-ba02-5205f9e8b47a, Duration=114ms)
```
```output
2022-02-16T21:07:11.340 [Information] INFORMATION: PowerShell HTTP trigger function processed a request.
2022-02-16T21:07:11.449 [Information] Executed 'Functions.DriveGearTemperatureService' (Succeeded, Id=25e2edc3-542f-4629-a152-cf9ed99680d8, Duration=1164ms)
```
向函数添加业务逻辑
向函数添加逻辑,检查所接收到的温度读数并为每个读数设置状态。
我们的函数应有一组温度读数。 以下 JSON 代码片段是我们向函数发送的请求正文的一个示例。 对于 JavaScript 或 PowerShell,数组的名称可能略有不同,但数组中的每个条目都有 ID、时间戳和温度。
{
"Readings": [
{
"driveGearId": 1,
"timestamp": 1534263995,
"temperature": 23
},
{
"driveGearId": 3,
"timestamp": 1534264048,
"temperature": 45
},
{
"driveGearId": 18,
"timestamp": 1534264050,
"temperature": 55
}
]
}
让我们用以下实现业务逻辑的代码来替换函数中的默认代码。
在 HttpTrigger1 函数窗格中打开 index.js 文件,并将其替换为以下代码。 进行此更改后,在命令栏上选择“保存”以保存对文件的更新。
module.exports = function (context, req) {
context.log('Drive Gear Temperature Service triggered');
if (req.body && req.body.readings) {
req.body.readings.forEach(function(reading) {
if(reading.temperature<=25) {
reading.status = 'OK';
} else if (reading.temperature<=50) {
reading.status = 'CAUTION';
} else {
reading.status = 'DANGER'
}
context.log('Reading is ' + reading.status);
});
context.res = {
// status: 200, /* Defaults to 200 */
body: {
"readings": req.body.readings
}
};
}
else {
context.res = {
status: 400,
body: "Please send an array of readings in the request body"
};
}
context.done();
};
我们所添加的逻辑非常直接。 我们循环访问数组,并根据温度字段的值将状态设置为“正常”、“警告”或“危险”。 将这组读数发送回去,其中每个条目包含状态字段。
在窗格底部展开“日志”时,请注意 Log
语句。 在该函数运行时,这些语句会在日志窗口中添加消息。
测试业务逻辑
我们将使用“开发人员”>“代码 + 测试”中的“测试/运行”功能来测试函数。
在“代码 + 测试”选项卡上,选择“测试/运行”。 在“输入”选项卡中,将“正文”文本框的内容替换为以下代码,以创建示例请求。
{ "readings": [ { "driveGearId": 1, "timestamp": 1534263995, "temperature": 23 }, { "driveGearId": 3, "timestamp": 1534264048, "temperature": 45 }, { "driveGearId": 18, "timestamp": 1534264050, "temperature": 55 } ] }
打开 run.ps1 文件并将其内容替换为以下代码。 进行此更改后,在命令栏上选择“保存”以保存对文件的更新。
using namespace System.Net
param($Request, $TriggerMetadata)
Write-Host "Drive Gear Temperature Service triggered"
$readings = $Request.Body.Readings
if ($readings) {
foreach ($reading in $readings) {
if ($reading.temperature -le 25) {
$reading.Status = "OK"
}
elseif ($reading.temperature -le 50) {
$reading.Status = "CAUTION"
}
else {
$reading.Status = "DANGER"
}
Write-Host "Reading is $($reading.Status)"
}
$status = [HttpStatusCode]::OK
$body = $readings
}
else {
$status = [HttpStatusCode]::BadRequest
$body = "Please send an array of readings in the request body"
}
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = $status
Body = $body
})
我们所添加的逻辑非常直接。 我们循环访问数组,并根据温度字段的值将状态设置为“正常”、“警告”或“危险”。 将这组读数发送回去,其中每个条目包含状态字段。
请注意对 Write-Host
cmdlet 的调用。 在该函数运行时,这些语句会在日志窗口中添加消息。
测试业务逻辑
我们将使用“开发人员”>“代码 + 测试”中的“测试/运行”功能来测试函数。
在“代码 + 测试”选项卡上,选择“测试/运行”。 在“输入”选项卡中,将“正文”文本框的内容替换为以下代码,以创建示例请求。
{ "Readings": [ { "driveGearId": 1, "timestamp": 1534263995, "temperature": 23 }, { "driveGearId": 3, "timestamp": 1534264048, "temperature": 45 }, { "driveGearId": 18, "timestamp": 1534264050, "temperature": 55 } ] }
选择“运行”。 “输出”选项卡显示 HTTP 响应代码和内容。 若要查看日志消息,请在窗格底部的浮出控件中打开“日志”选项卡(如果尚未打开)。 下面的图像显示的是输出窗格中的响应以及“日志”窗格中的消息的示例。
“输出”选项卡显示状态字段已正确添加到每个读数。
若要查看请求是否已记录到 Application Insights,请在左侧的“开发人员”菜单中选择“监视”。 此时将显示函数的“监视”窗格。
窗格的“调用”选项卡显示每个函数调用的“调用跟踪”。 选择其中一项调用的“日期(UTC)”值,然后查看有关函数执行的详细信息。