练习 - 向函数应用添加逻辑

已完成

让我们继续介绍齿轮传动示例,并添加温度服务的逻辑。 具体而言,我们将从 HTTP 请求接收数据。

函数要求

首先,我们需要为逻辑定义一些要求:

  • 从 0 到 25 度的温度应被标记为“正常”。
  • 25 度以上至 50 度的温度应被标记为“警告”。
  • 超过 50 度的温度应被标记为“危险”。

向函数应用添加一个函数

如之前单元中所述,Azure 提供了可帮助你生成函数的模板。 在本单元中,你将使用 HttpTrigger 模板来实现温度服务。

  1. 在上一个练习中,你部署了函数应用并打开了它。 如果它尚未打开,可从主页打开它,方法是选择“所有资源”,然后选择名为 escalator-functions-xxx 之类的函数应用。

  2. 在“函数应用”屏幕的“函数”选项卡下,选择“在 Azure 门户中创建”。 此时将显示“创建函数”窗格。

  3. 在“选择模板”下选择“HTTP 触发器”,然后选择“下一步”

  1. 将“函数名称”保留为“HttpTrigger1”,将“授权级别”保留为“函数”,然后选择“创建”。 函数 HttpTrigger1 已创建并显示在 HttpTrigger1 函数窗格中

  2. 选择“代码 + 测试”选项卡。代码编辑器随即打开,其中显示函数的 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 响应发送。

  1. 在“模板详细信息”部分的“新建函数”字段中,输入“DriveGearTemperatureService”。 将“授权级别”保留为“函数”,然后选择“创建”以创建函数。 此时将显示 DriveGearTemperatureService 函数的“概述”窗格。

  2. 在“函数”菜单中,选择“代码 + 测试”。 此时会打开代码编辑器,其中显示 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”,回显请求中发送的名称。

  3. 从源下拉列表选择“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。

  1. 展开触发器函数窗格底部的“日志”框架。 在日志框架顶部的下拉列表中选择“文件系统日志”。 日志框架应开始每分钟积累跟踪通知。

  2. 若要查找函数的终结点 URL,请在命令栏中选择“获取函数 URL”,如下图所示。 通过选择 URL 末尾的“复制到剪贴板”图标来保存此 URL。 将此链接存储到记事本或类似应用中,以备后用。

    显示函数编辑器的 Azure 门户屏幕截图,其中突出显示了“获取函数 URL”按钮。

  3. 打开命令提示符并运行 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 标头传递。

  1. 若要查找函数密钥,请在“概述”菜单的“函数”选项卡下选择函数名称(例如 HttpTriger1),以打开“代码 + 测试”菜单。 然后,选择“函数密钥”选项卡。

  2. 默认情况下,函数密钥值处于隐藏状态。 通过选择“显示值”来显示默认函数密钥值。 将“值”字段的内容复制到剪贴板,然后将此密钥存储在记事本或类似应用中供以后使用。

    显示“函数密钥”窗格的屏幕截图,其中突出显示了显示的函数密钥。

  3. 若要使用函数密钥测试函数,请打开命令提示符并运行 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>
    
  4. 查看 cURL 命令并验证其是否具有以下值:

    • 已添加 application/json 类型的 Content-Type 标头值。
    • 已将函数密钥作为标头值 x-functions-key 传递。
    • 已使用 POST 请求。
    • 使用函数的 URL 传递了 Azure 函数。
  5. 查看日志。

    “代码 + 测试”窗格应打开一个显示日志文件输出的会话(确保在“日志”窗格顶部的下拉列表中选择了“文件系统日志”)。 日志文件根据请求状态进行更新,该状态应如下所示:

```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 语句。 在该函数运行时,这些语句会在日志窗口中添加消息。

测试业务逻辑

我们将使用“开发人员”>“代码 + 测试”中的“测试/运行”功能来测试函数。

  1. 在“代码 + 测试”选项卡上,选择“测试/运行”。 在“输入”选项卡中,将“正文”文本框的内容替换为以下代码,以创建示例请求。

    {
        "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 的调用。 在该函数运行时,这些语句会在日志窗口中添加消息。

测试业务逻辑

我们将使用“开发人员”>“代码 + 测试”中的“测试/运行”功能来测试函数。

  1. 在“代码 + 测试”选项卡上,选择“测试/运行”。 在“输入”选项卡中,将“正文”文本框的内容替换为以下代码,以创建示例请求。

    {
        "Readings": [
            {
                "driveGearId": 1,
                "timestamp": 1534263995,
                "temperature": 23
            },
            {
                "driveGearId": 3,
                "timestamp": 1534264048,
                "temperature": 45
            },
            {
                "driveGearId": 18,
                "timestamp": 1534264050,
                "temperature": 55
            }
        ]
    }
    
  1. 选择“运行”。 “输出”选项卡显示 HTTP 响应代码和内容。 若要查看日志消息,请在窗格底部的浮出控件中打开“日志”选项卡(如果尚未打开)。 下面的图像显示的是输出窗格中的响应以及“日志”窗格中的消息的示例。

    Azure 函数编辑器的屏幕截图,其中显示了“测试”和“日志”选项卡。

    “输出”选项卡显示状态字段已正确添加到每个读数

  2. 若要查看请求是否已记录到 Application Insights,请在左侧的“开发人员”菜单中选择“监视”。 此时将显示函数的“监视”窗格。

    窗格的“调用”选项卡显示每个函数调用的“调用跟踪”。 选择其中一项调用的“日期(UTC)”值,然后查看有关函数执行的详细信息。