练习 - 使用 Durable Functions 创建工作流

已完成

在此练习中,你使用上一个单元的示例场景来了解如何在 Azure 门户中使用 Durable Functions 创建审批工作流。

创建函数应用

  1. 使用激活沙盒时所用的同一帐户登录到 Azure 门户

  2. 在 Azure 门户菜单上或在“主页”中,选择“Azure 服务”下的“创建资源”。 此时会显示“创建资源”窗格。

  3. 搜索并选择“函数应用”。 此时将显示“创建函数应用”窗格。

  4. 在“基本信息”选项卡上,为每个设置输入以下值。

    设置 说明
    项目详细信息
    订阅 Concierge 订阅 指定要在其下创建此新函数应用的订阅。
    资源组 从下拉列表中,选择 [沙盒资源组名称] 指定要在其中创建函数应用的资源组的名称。 我们将在激活沙盒时分配的沙盒资源组(即[沙盒资源组名称])中创建函数应用。
    实例详细信息
    Function App 名称 [全局唯一名称] 指定用于标识新函数应用的名称。 有效字符为 a-z0-9-
    发布 代码 指定函数使用代码而不是容器。
    运行时堆栈 Node.js 指定使用 JavaScript 编写此模块中的示例代码。
    版本 20 LTS 指定运行时堆栈的版本。
    区域 [从本部分后面的列表中选择] 选择离你最近且属于下面允许的沙盒区域的位置。
    操作系统
    操作系统 Windows 指定用于托管函数应用的操作系统。
    规划
    计划类型 消耗(无服务器) 指定托管计划,用于定义如何将资源分配给函数应用。 在默认“消耗计划”中,会根据函数的需求动态添加资源。 在此无服务器托管模型中,只需根据函数的运行时间付费。

    使用免费沙盒,可以在部分 Azure 全球区域中创建资源。 创建资源时,请从下面的列表中选择一个区域:

    • 美国西部 2
    • 美国中南部
    • 美国中部
    • 美国东部
    • 西欧
    • 东南亚
    • Japan East
    • Brazil South
    • Australia Southeast
    • 印度中部
  5. 选择“下一页:存储”。

  6. 在“存储”选项卡上,为每个设置输入以下值。

    设置 说明
    存储
    存储帐户 [全局唯一名称] 指定函数应用使用的新存储帐户的名称(不需要与为函数指定的全局唯一名称匹配)。 存储帐户名称必须为 3 到 24 个字符,并且只能包含数字和小写字母。 此对话框使用动态生成的唯一名称自动填充字段。 但是,可以任意使用不同的名称,甚至是现有帐户名称。
  7. 选择“下一页:网络”。 接受默认值。

  8. 选择“下一步: 监视”。

  9. 在“监视”选项卡上,为设置输入以下值。

    设置 说明
    Application Insights
    启用 Application Insights 指定对此模块禁用 Application Insights。
  10. 选择“查看和创建”,查看已配置的选项。 如果对选项感到满意,则选择“创建”来预配和部署函数应用。

等待部署完成,然后继续。 部署可能需要几分钟时间。

安装 durable-functions npm 包

我们要创建 JavaScript Durable Functions,所以需要安装 durable-functions npm 包。 为此,请执行下列步骤。

  1. 选择“转到资源”以选择函数应用。 系统将显示函数应用窗格。

  2. 在左侧菜单窗格中的“开发工具”下,选择“应用服务编辑器(预览)”,然后选择“打开编辑器”。 此时将在新的浏览器窗口中显示“应用服务编辑器”快速入门窗格。

  3. 在左侧菜单窗格中,突出显示 WWWROOT 文件夹。

  4. 在左侧工具栏菜单中,选择“打开控制台”图标。

    此操作将启动控制台。 可使用此控制台访问托管函数的 Web 服务器,并为该函数编写代码。

  5. 创建新的“package.json”文件。

    • 在控制台中运行以下命令,创建新的 JSON 文件,并在编辑器中将其打开。

      touch package.json
      open package.json
      
    • 添加以下代码。

      {
        "name": "example",
        "version": "1.0.0"
      }
      

      example 替换为包的名称。 例如,可以使用先前为函数指定的全局唯一名称。

  6. 选择 Ctrl+S 保存文件,然后选择 Ctrl+Q 关闭文档。

  7. 切换回 Azure 门户。

  8. 在左侧菜单栏中的“开发工具”下,选择“控制台”。 此时将显示函数应用的“控制台”窗格。

  9. 运行以下命令:

    npm install durable-functions
    

    此命令指示节点包管理器安装 durable-functions 包和任何必需的依赖项。 安装可能需要几分钟才能完成,并且节点包管理器可能会显示一些警告(可忽略这些警告)。 如果系统提示安装较新版本的 npm,请使用错误中提供的命令安装较新版本,然后在安装新版本后安装 durable-functions 包。

    等待所有包完成安装。

  10. 在左侧菜单窗格中,向上滚动并选择“概述”,然后在顶部菜单栏中选择“重新启动”,并在系统提示是否重新启动时选择“是”。

    等待重启过程完成,然后继续。

创建用于提交设计提案的客户端函数

  1. 在 Azure 门户菜单或主页的“最近使用的资源”下,选择“查看全部”,然后选择你的函数应用。 系统将显示函数应用窗格。

  2. 在“概述”页上,选择屏幕中间的“函数”选项卡

  3. 选择“在 Azure 门户中创建”按钮。 此时将显示“创建函数”窗格。

  4. 在“选择模板”下的“筛选器”框中,输入“Durable Functions HTTP starter”,然后从列表中选择该模板。 此模板创建持久函数,用于响应 HTTP 请求。

  5. 在“模板详细信息”下,对于“新建函数”字段,输入“HttpStart”作为函数名称,在“授权级别”字段中,选择“函数”,然后选择“创建”。 此时将显示函数的“HttpStart”窗格。

  6. 在左侧菜单窗格的“开发人员”下,选择“代码 + 测试”。 此时,函数的“代码和测试”窗格显示。

    此时将在编辑器中显示 index.js 文件的代码。 文件应与下面的示例类似:

    const df = require("durable-functions");
    
    module.exports = async function (context, req) {
        const client = df.getClient(context);
        const instanceId = await client.startNew(req.params.functionName, undefined, req.body);
    
        context.log(`Started orchestration with ID = '${instanceId}'.`);
    
        return client.createCheckStatusResponse(context.bindingData.req, instanceId);
    };
    
  7. 在函数中的文件的下拉列表中,选择“function.json”以查看与新函数关联的绑定。 此信息指定任何身份验证要求,以及触发该函数的 HTTP 方法。 此文件还指定该函数是启动业务流程进程的客户端。 文件应与下面的示例类似:

    {
      "bindings": [
        {
          "authLevel": "function",
          "name": "req",
          "type": "httpTrigger",
          "direction": "in",
          "route": "orchestrators/{functionName}",
          "methods": [
            "post",
            "get"
          ]
        },
        {
          "name": "$return",
          "type": "http",
          "direction": "out"
        },
        {
          "name": "starter",
          "type": "orchestrationClient",
          "direction": "in"
        }
      ]
    }
    

    注意

    绑定将触发器的资源和其他项相关联。 绑定是一种声明性机制,无需将引用硬编码到代码中的其他服务和函数。

创建业务流程协调函数

  1. 在 Azure 门户菜单或主页的“最近使用的资源”下,选择“查看全部”,然后选择你的函数应用。 系统将显示函数应用窗格。

  2. 在“概述”页上,选择屏幕中间的“函数”选项卡

  3. 在“函数”菜单栏中,选择“创建”。 此时将显示“创建函数”窗格。

  4. 在“选择模板”下的“筛选器”框中,输入“Durable Functions orchestrator”,然后从列表中选择该模板。 此模板创建持久函数,用于协调函数的执行。

  5. 在“模板详细信息”下,对于“新建函数”字段,输入“OrchFunction”作为函数名称,然后选择“创建”。 此时将显示“OrchFunction”函数窗格。

  6. 在左侧菜单窗格的“开发人员”下,选择“代码 + 测试”。 此时,函数的“代码和测试”窗格显示。

    此时将在编辑器中显示 index.js 文件的代码。

  7. 用下面的代码替换现有代码。

    const df = require("durable-functions");
    
    module.exports = df.orchestrator(function* (context) {
        const outputs = [];
    
        /*
        * We will call the approval activity with a reject and an approved to simulate both
        */
    
        outputs.push(yield context.df.callActivity("Approval", "Approved"));
        outputs.push(yield context.df.callActivity("Approval", "Rejected"));
    
        return outputs;
    });
    

    此代码调用名为“Approval”的 Activity 函数,稍后会创建该函数。 业务流程协调程序函数中的代码调用 Approval 函数两次。 第一次模拟“接受提案”,第二次测试“提案拒绝”逻辑。

    每次调用返回的值组合在一起,并传回客户端函数。 在生产环境中,业务流程函数调用一系列活动函数,用于作出接受/拒绝决定,并返回这些活动的结果。

  8. 在顶部菜单栏中,选择“保存”以保存新函数。

创建活动函数

  1. 在 Azure 门户菜单或主页的“最近使用的资源”下,选择“查看全部”,然后选择你的函数应用。 系统将显示函数应用窗格。

  2. 在“概述”页上,选择屏幕中间的“函数”选项卡

  3. 在“函数”菜单栏中,选择“创建”。 此时将显示“创建函数”窗格。

  4. 在“选择模板”下的“筛选器”框中,输入“Durable Functions activity”,然后从列表中选择该模板。 此模板创建一个持久函数,该函数在业务流程协调程序函数调用活动时运行。

  5. 在“模板详细信息”下,对于“新建函数”字段,输入“Approval”作为函数名称,然后选择“创建”。 此时将显示函数应用的“批准”窗格。

  6. 在左侧菜单窗格的“开发人员”下,选择“代码 + 测试”。 此时,函数的“代码和测试”窗格显示。

    此时将在编辑器中显示 index.js 文件的代码。

  7. 用下面的代码替换现有代码。

    module.exports = async function (context) {
        return `Your project design proposal has been -  ${context.bindings.name}!`;
    };
    

    此函数返回一条指示提案状态的消息。 表达式 context.bindings.name 的结果是 AcceptedRejected,具体取决于从业务流程协调程序传递到函数的参数。 在真实世界的方案中,需要在此函数中添加用于处理接受或拒绝操作的逻辑。

  8. 在顶部菜单栏中,选择“保存”以保存新函数。

确认 Durable Functions 工作流启动

  1. 在 Azure 门户菜单或主页的“最近使用的资源”下,选择“查看全部”,然后选择你的函数应用。 系统将显示函数应用窗格。

  2. 选择页面中间的“函数”选项卡

  3. 选择“HttpStart”函数。 此时将显示函数的“HttpStart”窗格。

  4. 在顶部菜单栏中,选择“获取函数 URL”,然后复制 URL。 URL 应与下面的示例类似:

    https://example.azurewebsites.net/api/orchestrators/{functionName}?code=AbCdEfGhIjKlMnOpQrStUvWxYz==
    

    使用此 URL 运行函数。

  5. 打开新浏览器窗口,并转到已复制的 URL。 在 URL 中,将 {functionName} 占位符替换为 OrchFunction,这应类似于以下示例:

    https://example.azurewebsites.net/api/orchestrators/OrchFunction?code=AbCdEfGhIjKlMnOpQrStUvWxYz==
    

    响应消息包含一组 URI 终结点,这些终结点可以用来监视并管理执行,该执行应与以下示例类似:

    {
      "id": "f0e1d2c3b4a5968778695a4b3c2d1e0f",
      "statusQueryGetUri": "https://example.azurewebsites.net/...",
      "sendEventPostUri": "https://example.azurewebsites.net/...",
      "terminatePostUri": "https://example.azurewebsites.net/...",
      "rewindPostUri": "https://example.azurewebsites.net/...",
      "purgeHistoryDeleteUri": "https://example.azurewebsites.net/..."
    }
    
  6. 复制 statusQueryGetUri 值,并使用 Web 浏览器转到此 URL。 应看到类似于以下示例的响应消息:

    {
      "name": "OrchFunction",
      "instanceId": "f0e1d2c3b4a5968778695a4b3c2d1e0f",
      "runtimeStatus": "Completed",
      "input": null,
      "customStatus": null,
      "output": [
        "Your project design proposal has been -  Approved!",
        "Your project design proposal has been -  Rejected!"
      ],
      "createdTime": "2019-04-16T15:23:03Z",
      "lastUpdatedTime": "2019-04-16T15:23:35Z"
    }
    

    前面曾提到,业务流程函数运行两次活动函数。 第一次,Activity 函数指示已接受项目提案。 第二次运行,提案被拒绝。 业务流程函数将这两个函数调用中的消息合并,然后将其返回到客户端函数。