65.9K
CodeProject 正在变化。 阅读更多。
Home

学习 Azure Functions: 精通 Blob 触发器和队列存储触发器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.77/5 (19投票s)

2019年4月4日

CPOL

13分钟阅读

viewsIcon

31955

downloadIcon

393

如何精通 Blob 触发器和队列存储触发器。

目录

前言

本文是提交给 CodeProject 的 Serverless Challenge 比赛的作品。比赛于 2019 年 3 月 11 日正式开始,并于 2019 年 4 月 30 日结束。

本文将帮助开发人员熟悉无服务器函数,了解 Azure Functions 是什么,如何从 Visual Studio 创建 Azure Function,以及如何在 Azure 上发布和测试函数。本文将重点介绍熟悉 Azure 提供的 Blob 和队列存储。

学习无服务器 Azure Functions

以下两篇文章将全面介绍 HTTP 触发的 Azure Functions、队列触发的 Azure Functions 和 Blob 触发的 Azure Functions。

必备组件

本文的读者应首先阅读学习 Azure Functions 的文章,即 在 Visual Studio 2017 中创建 Azure Functions。我们将从该文章的结束处开始。

引言

在上一篇学习 Azure Functions 的文章中,我们学习了如何创建 Azure 帐户,设置开发环境以编写 HTTP 触发的 Azure Functions。我们在 Visual Studio 2017 中本地测试了这些函数,然后将函数发布到 Azure,并通过 Postman 测试了已发布的函数。我们还探讨了如何在本地开发环境中调试 Azure Function,不仅如此,我们还探索了如何在 Visual Studio 中调试 Azure 门户上已预编译的已部署 Azure Function。我们使用的案例研究是最终用户提交信用卡申请,我们的函数通过仅返回一个包含申请人姓名的虚拟文本“Hi XYZ, your application is accepted”来确认。

Azure 存储

Azure 存储服务包含各种属性。第一个是 Blob 存储。Blob 本质上就像单独的文件。Blob 存储可以存储日志文件、图像和 Word 文档等,例如,Blob 存储在 Blob 容器中。Blob 容器可以想象成文件文件夹。存储的 Blob 可以通过 URL 作为 REST 端点访问,也可以通过代码访问。另一个存储服务是 Azure 队列存储。可以创建一个 Azure 队列来发送和接收消息。单个队列项的最大允许大小为 64 KB,因此队列中的项应小于此大小。Azure 队列可用于创建处理管道。

Azure 还提供 Azure 表存储,这是一个结构化的 NoSQL 数据存储,这意味着它具有无模式设计。Azure 表存储比其他传统关系数据模型更灵活。无模式设计可以存储设备信息、元数据或通讯簿等信息。另一个是 Azure Cosmos DB,它提供了超越 Azure 表存储的几个附加功能,例如,它从一开始就设计用于支持数据的全局分发。Azure 存储还包括磁盘存储和文件存储。

Azure 存储模拟器

Azure 存储模拟器为 Azure Blob 服务、Azure 队列服务和 Azure 表服务提供本地开发机器模拟。这意味着我们可以在本地开发和测试使用 Azure 存储的函数,而无需网络连接。当我们使用本地模拟器时,我们不会在云中读取或写入任何 Azure 存储内容,这意味着在开发过程中不会产生任何事务成本。有几种方法可以安装 Azure 存储模拟器。首先是作为 Azure SDK 安装程序的一部分,您还可以在 Microsoft 网站上找到独立的安装程序。

添加 Azure 队列存储

我们将使用我们在上一篇文章中开发的相同应用程序,并从那里开始。我们将尝试将收到的信用卡申请写入队列存储。因此,请打开 Visual Studio 和我们在上一个教程中开发的解决方案。确保您的计算机上安装的 Azure 存储模拟器正在运行,具体步骤如下。

  1. 打开 Azure 存储模拟器。

  2. 一旦成功启动,就意味着它正在运行。

  3. 现在,在 `ApplyForCC` 的现有 `Run` 方法中,添加一个名为“`ccApplication`”或您选择的名称的 `Queue` 属性。在方法体中,从请求正文中读取 `CCApplication`,并将其添加到 `ccApplicationQueue`,然后返回响应。因此,在这里我们从请求正文中获取 `CCApplication` 并将其添加到我们新定义的队列中。
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Threading.Tasks;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.Azure.WebJobs.Host;
    
    namespace LearnAzureFunctions
    {
      public static class ApplyForCC
      {
        [FunctionName("ApplyForCC")]
        public static async Task<HttpResponseMessage> Run(
          [HttpTrigger(AuthorizationLevel.Function,
              "post",
              Route = null)]HttpRequestMessage req,
          [Queue("ccApplication")] 
                               IAsyncCollector<CCApplication> applicationQueue,
          TraceWriter log)
        {
          log.Info("C# HTTP trigger function processed a request.");
    
          CCApplication ccApplication = await req.Content.ReadAsAsync<CCApplication>();
          log.Info($"Received Credit Card Application from : {ccApplication.Name }");
          await applicationQueue.AddAsync(ccApplication);
          return req.CreateResponse(HttpStatusCode.OK,
            $"Application received and submitted for {ccApplication.Name}");
        }
      }
    }
  4. 请确保在您的 `local.settings.json` 文件中,设置如下:

  5. 运行应用程序。控制台窗口将启动。

  6. 现在,返回 Postman,并向本地 URL 发送请求,将 JSON 放入 `body` 标签中,如上篇文章所示。

  7. 收到响应后,打开 Visual Studio 中的云资源管理器,然后在 Local-> Storage Accounts-> Development-> Queues 下,您会找到一个新创建的队列,名称为“`ccapplication`”,即我们在 `Run` 方法中的 `queue` 属性中提供的名称。

  8. 双击队列,我们可以看到作为 JSON 对象在请求中传递的详细信息。队列已创建,详细信息已作为消息记录在队列中。

在 Azure 门户中创建存储帐户

我们已经了解了在使用函数时如何使用 Azure 存储模拟器。让我们看看如何设置一个云中的测试存储帐户,而不是依赖于模拟器。我们要做的第一件事是前往门户并创建一个新的存储帐户用于开发和测试目的。

  1. 返回 Azure 门户,单击“创建资源”并选择“存储帐户”。

  2. 提供存储帐户名称、位置、帐户种类。我选择了通用 v2 种类。只需检查并创建帐户。

  3. 验证通过后,点击 **创建** 按钮创建帐户。

  4. 之后,部署将完成,您将看到您的存储帐户已创建。

  5. 回到 Visual Studio 中的云资源管理器,然后在 Azure 帐户(不是本地开发帐户)下,检查“存储帐户”,您将看到显示的存储帐户名称。此存储帐户列出了 Blob 容器、队列和表存储作为存储容器的类型。

  6. 在 Azure 门户的存储帐户中,单击“访问密钥”以查看您帐户的访问密钥。

  7. 复制 `key1` 中显示的访问密钥。我们将使用此密钥从本地环境访问存储帐户,并将消息写入现在创建的存储帐户中的队列,而不是本地环境。

  8. 将复制的密钥粘贴到 `local.settings.json` 文件中的“`AzureWebJobsStorage`”字段中,如下图所示。

  9. 现在再次向 `ApplyForCC` 函数发出请求。我们在这里期望队列将在存储帐户中创建,而不是在本地创建,并且消息已写入该队列。

  10. 收到申请人“`Ekta`”的响应后,如上一步所示,转到云资源管理器并刷新在 Azure 门户上创建的存储帐户。

  11. 我们看到队列已在此存储帐户下创建,并且请求已作为消息记录在此队列中。

队列触发器 Azure Functions

现在是时候处理队列中收到的消息了。为了实现这一点,我们将创建一个队列触发器,当消息进入队列时,该函数将被触发以进一步处理消息。我们将再次创建一个 Azure Function,但这次不是 HTTP 触发器,而是 `Queue` 触发器函数。

  1. 在 Visual Studio 中,右键单击您的项目并添加一个名为 `ProcessCCApplication` 的新 Azure Function。

  2. 选择函数类型为 `Queue` 触发器,并在 `Path` 字段中提供队列名称,如下所示。

  3. 创建函数后,您将在 Visual Studio 中看到以下类生成,顶部定义了函数名称属性,并在 `Run` 方法中定义了 `QueueTrigger`。

  4. 添加一些业务逻辑来接受或拒绝申请。在 `ProcessCCApplication` 函数的 `Run` 方法中,定义两个变量作为函数的参数,即 `acceptedCCApplication` 和 `rejectedCCApplication`,并用 `Blob` 属性进行装饰,一个用于接受,一个用于拒绝。这里定义的业务逻辑是,只有当申请人的年收入超过 `100000` 且年龄大于 `23` 岁时,申请才会被接受,否则申请将被拒绝。我们将参数变量设置为 JSON 序列化的 `CCApplication` 对象,用于接受和拒绝,如下所示。

代码

using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Newtonsoft.Json;

namespace LearnAzureFunctions
{
  public static class ProcessCCApplication
  {
    [FunctionName("ProcessCCApplication")]
    public static void Run([QueueTrigger("ccapplication", Connection = "")]CCApplication ccApplication,
      [Blob("accepted-application/{rand-guid}")] out string acceptedCCApplication,
      [Blob("rejected-application/{rand-guid}")] out string rejectedCCApplication,
      TraceWriter log)
    {
      log.Info($"C# Queue trigger function processed: {ccApplication.Name}");

      bool isApplicationAccepted = ccApplication.YearlyIncome > 100000 && ccApplication.Age > 23;

      if (isApplicationAccepted)
      {
        acceptedCCApplication = JsonConvert.SerializeObject(ccApplication);
        rejectedCCApplication = null;
      }
      else
      {
        rejectedCCApplication = JsonConvert.SerializeObject(ccApplication);
        acceptedCCApplication = null;
      }
    }
  }
}

编译和测试队列触发器函数

  1. 编译解决方案并运行应用程序。一旦控制台启动,您就可以看到新添加的 Azure Function 在那里显示。

  2. 请记住,队列中已经有一个名为“`Ekta Mittal`”的申请人的消息。应用程序启动后,我们的队列触发器函数将立即激活,并持续监视我们在 Azure 存储中定义的队列是否有新消息。由于我们已经有一条消息,此触发器将处理该消息,您可以在控制台中看到它说“`Executing ‘ProcessCCApplication’ ….`”。处理完成后,它会显示“`Executed...`”。

  3. 回到云资源管理器中的 Blob 容器,我们看到 Blob 容器中有三个容器,其中两个是我们为 `Queue` 触发器在 `Run` 函数中定义的。

  4. 双击 `accepted-application` 容器,我们看到该容器有一个 blob,如果您双击右侧屏幕中的该 blob,它将下载该 blob 并尝试打开它。使用记事本打开 blob。

  5. 我们看到 blob 包含“`Ekta Mittal`”请求的消息。由于申请人的年收入大于 `100000` 且年龄大于 `23` 岁,因此申请被接受并放入 `accepted-application` 容器。

  6. 同样,使用一个年收入为 `50000` 且年龄为 `17` 的新申请人再发一个请求,即违反业务逻辑。您会看到申请将被处理,并且 `rejected-application` blob 容器现在将包含该被拒绝申请的 blob。您可以通过下载再次打开 blob。

Blob 触发器 Azure Functions

顾名思义,Blob 触发器函数是在写入 Blob 时将执行的函数。因此,如果我们回顾一下,我们首先创建了一个 HTTP 触发器函数来接收信用卡申请人的 HTTP 请求,然后我们将所有申请放入一个队列以在收到申请时进行进一步处理。再次,我们创建了一个队列触发器函数,该函数在接受或拒绝队列中有消息时被触发,并将处理后的申请放入各自的 Blob 中,这些 Blob 存储在 Azure 存储上,可以下载并作为文本文件打开。现在我们将编写一个 Blob 触发器函数,当队列触发器函数写入 Blob 时,该函数将被触发,以进一步处理接受和拒绝的申请。

  1. 在 Visual Studio 中右键单击项目,并添加一个新的 Azure Function。

  2. 将函数命名为“`ProcessCCApplication`”。此 Blob 触发器函数将用于接受的应用程序,我们将以类似的方式为被拒绝的应用程序创建一个新函数。

  3. 选择函数类型为 Blob 触发器,并将路径设置为我们在队列触发器函数中定义的接受的 Blob 触发器的名称,即“`accepted-application`”。

  4. 添加 Azure Function 后,您将看到如下所示的代码。

  5. 将类型为 `Stream` 的 `myBlob` 参数替换为名为 `ccApplicationJson` 的 `string` 变量,因为我们期望从 Blob 中获取 JSON。在 `usings` 中添加 `Newtonsoft.Json` 命名空间,并在函数体中,通过反序列化 Blob 中为已接受应用程序写入的序列化 JSON 来获取 `CCApplication` 模型。最后记录申请人的姓名。这将确保我们的 Blob 触发器被命中,并且我们记录了申请人的姓名。

  6. 同样,为拒绝的应用程序添加另一个 Blob 触发器函数。

  7. 函数添加后,代码应如下所示。

    替换 `Stream` 参数和函数体,如下面的代码所示。

    using System.IO;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Host;
    using Newtonsoft.Json;
    
    namespace LearnAzureFunctions
    {
      public static class ProcessRejectedCCApplication
      {
        [FunctionName("ProcessRejectedCCApplication")]
        public static void Run([BlobTrigger("rejected-application/{name}", 
                                Connection = "")]string ccApplicationJson,
          string name, TraceWriter log)
        {
          CCApplication ccApplication = 
                   JsonConvert.DeserializeObject<CCApplication>(ccApplicationJson);
          log.Info($"ProcessRejectedCCApplication Blob Trigger for \n Name:{ccApplication.Name}");
        }
      }
    }

现在我们已经完成了函数的编写。是时候测试 Blob 触发器函数了。

发布和测试 Blob 触发器函数

  1. 编译并运行应用程序,我们看到控制台中的独立服务器识别出两个新添加的函数。现在,请记住,我们已经在 Blob 存储中有两个请求,一个是“`Ekta Mittal`”的已接受申请,另一个是“`Mini Mittal`”的已拒绝申请。因此,一旦应用程序运行,接受和拒绝应用程序的 Blob 触发器函数就会触发并执行现有的 Blob,通过反序列化 JSON 从这些 Blob 中读取信息,并记录申请人的姓名。

  2. 这些函数仍然在我们本地环境中,而不是像我们的队列一样在 Azure 门户上。因此,只需将函数发布到 Azure。右键单击项目并单击 **发布**。

  3. 您将看到我们在上一篇文章中首次发布 HTTP 触发器函数时创建的现有发布配置文件。点击 **发布** 按钮。

  4. 发布后,返回 Azure 门户,在您的 `CCAppFunction` 下,您可以看到我们到目前为止创建的所有四个函数,即一个 HTTP 触发器函数,一个 `Queue` 触发器函数和两个 Blob 触发器函数。

  5. 现在,由于函数作为预编译的无服务器函数发布到 Azure,我们可以对其进行测试。现在切换回 Postman,并向 `ApplyForCC` 函数的 URL 发出请求,您可以在 Azure 门户中单击 `ApplyForCC` 函数的详细信息部分找到该 URL。上一篇文章也对此进行了说明。使用姓名“`Rocky`”,年龄 `35` 岁,年收入 `500000` 发出请求。

  6. 为申请人“`Docky`”,年龄 `16` 岁,年收入 `30000` 发出另一个请求。

  7. 现在,如果我们转到 Visual Studio 中 Azure 帐户的云资源管理器,我们会看到 `ccappfunction` 存储帐户下的队列为“`ccApplication`”。

  8. 我们在 Blob 容器部分下看到了 `accepted-application` 和 `rejected-application` Blob 容器。

  9. 双击 `accepted-application` blob 以下载并查看 blob。我们看到 **Rocky** 的请求在此处作为已接受应用程序记录在 blob 存储中。

  10. 双击 `accepted-application` blob 以下载并查看 blob。我们看到 **Dockey** 的请求在此处作为已拒绝应用程序记录在 blob 存储中,因为它不符合接受的最低年龄和年收入标准。

这表明我们所有的函数都运行得非常顺利,并且以管道方式完成工作。

结论

在本文中,我们介绍了 Azure 队列触发器和 Azure Blob 触发器函数。我们逐步完成了案例研究,以涵盖整个主题。无服务器函数在开发和使用方面都很有趣。

Github 上的源代码

© . All rights reserved.