你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

Azure 事件网格适用于 .NET 的客户端库 - 版本 4.20.0

通过 Azure 事件网格,可使用基于事件的体系结构轻松生成应用程序。 事件网格服务完全管理任何应用程序从任何源到任何目标的所有事件路由。 Azure 服务事件和自定义事件可以直接发布到服务,然后可以筛选事件并将其发送到各种收件人,例如内置处理程序或自定义 Webhook。 若要详细了解Azure 事件网格:什么是事件网格?

使用用于Azure 事件网格的客户端库可以:

入门

安装包

NuGet 安装客户端库:

dotnet add package Azure.Messaging.EventGrid

先决条件

必须具有 Azure 订阅 和具有自定义事件网格主题或域的 Azure 资源组。 按照此分步教程注册事件网格资源提供程序并使用Azure 门户创建事件网格主题。 有一个 类似的教程 使用 Azure CLI

对客户端进行身份验证

为了使客户端库与主题或域交互,需要 endpoint 事件网格主题的 和 , credential可以使用主题的访问密钥创建 。

可以在 Azure 门户中 或使用下面的 Azure CLI 代码片段找到事件网格主题的终结点。

az eventgrid topic show --name <your-resource-name> --resource-group <your-resource-group-name> --query "endpoint"

还可以通过 门户或使用以下 Azure CLI 代码片段找到访问密钥:

az eventgrid topic key list --name <your-resource-name> --resource-group <your-resource-group-name> --query "key1"

使用主题访问密钥进行身份验证

获得访问密钥和主题终结点后,可以按如下所示创建发布者客户端:

EventGridPublisherClient client = new EventGridPublisherClient(
    new Uri("<endpoint>"),
    new AzureKeyCredential("<access-key>"));

使用共享访问签名进行身份验证

事件网格还支持使用共享访问签名进行身份验证,该签名允许提供对在一定时间过期的资源的访问权限,而无需共享访问密钥。 通常,工作流是,一个应用程序将生成 SAS 字符串,并将该字符串交给使用该字符串的另一个应用程序。 生成 SAS:

var builder = new EventGridSasBuilder(new Uri(topicEndpoint), DateTimeOffset.Now.AddHours(1));
var keyCredential = new AzureKeyCredential(topicAccessKey);
string sasToken = builder.GenerateSas(keyCredential);

下面是从使用者的角度使用它的方式:

var sasCredential = new AzureSasCredential(sasToken);
EventGridPublisherClient client = new EventGridPublisherClient(
    new Uri(topicEndpoint),
    sasCredential);

EventGridPublisherClient 还通过 EventGridPublisherClientOptions接受一组配置选项。 例如,可以指定用于将事件数据序列化为 JSON 的自定义序列化程序。

使用 Azure Active Directory 进行身份验证

Azure 事件网格提供与 Azure Active Directory (Azure AD) 的集成,以便对请求进行基于标识的身份验证。 借助 Azure AD,可以使用基于角色的访问控制 (RBAC) 向用户、组或应用程序授予对Azure 事件网格资源的访问权限。 Azure 标识库为身份验证提供简单的 Azure Active Directory 支持。

若要使用 Azure Active Directory 将事件发送到主题或域,应为经过身份验证的标识分配“EventGrid 数据发送者”角色。

EventGridPublisherClient client = new EventGridPublisherClient(
    new Uri(topicEndpoint),
    new DefaultAzureCredential());

关键概念

有关常规事件网格概念的信息:Azure 事件网格中的概念

EventGridPublisherClient

发布者将事件发送到事件网格服务。 Microsoft 发布了几个 Azure 服务的事件。 可以使用 从自己的应用程序 EventGridPublisherClient发布事件。

事件架构

事件是完全描述系统中发生的事件的最小信息量。 事件网格支持多个架构来编码事件。 创建自定义主题或域时,可以指定发布事件时将使用的架构。

事件网格架构

虽然可以将主题配置为使用自定义架构,但使用已定义的事件网格架构更为常见。 请参阅 此处的规范和要求。

CloudEvents v1.0 架构

另一个选项是使用 CloudEvents v1.0 架构。 CloudEvents 是一个云原生计算基础项目,它生成用于以通用方式描述事件数据的规范。 可 在此处找到 CloudEvents 的服务摘要。

无论主题或域配置为使用哪种架构, EventGridPublisherClient 都将用于向主题或域发布事件。 SendEvents使用 或 SendEventsAsync 方法进行发布。

事件传送

事件网格传递给使用者的事件以 JSON 的形式传递。 根据要传递到的使用者类型,事件网格服务可能会将一个或多个事件作为单个有效负载的一部分传递。 根据事件作为哪个架构传递事件,事件的处理方式会有所不同。 但是,常规模式将保持不变:

  • 将事件从 JSON 分析为单个事件。 根据事件网格或 CloudEvents) (事件架构,现在可以访问信封上事件的基本信息, (所有事件存在的属性,例如事件时间和类型) 。
  • 反序列化事件数据。 EventGridEvent给定 或 CloudEvent,用户可以通过反序列化为特定类型来尝试访问事件有效负载或数据。 此时,可以提供自定义序列化程序来正确解码数据。

线程安全

我们保证所有客户端实例方法都是线程安全的,并且相互独立, (准则) 。 这可确保重用客户端实例的建议始终是安全的,即使跨线程也是如此。

其他概念

客户端选项 | 访问响应 | 长时间运行的操作 | 处理失败 | 诊断 | 嘲笑 | 客户端生存期

示例

将事件网格事件发布到事件网格主题

使用 执行将事件发布到事件网格。EventGridPublisherClient 使用提供 SendEvent/SendEventAsync 的方法将单个事件发布到主题。

// Add EventGridEvents to a list to publish to the topic
EventGridEvent egEvent =
    new EventGridEvent(
        "ExampleEventSubject",
        "Example.EventType",
        "1.0",
        "This is the event data");

// Send the event
await client.SendEventAsync(egEvent);

若要发布一批事件,请使用 SendEvents/SendEventsAsync 方法。

// Example of a custom ObjectSerializer used to serialize the event payload to JSON
var myCustomDataSerializer = new JsonObjectSerializer(
    new JsonSerializerOptions()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    });

// Add EventGridEvents to a list to publish to the topic
List<EventGridEvent> eventsList = new List<EventGridEvent>
{
    // EventGridEvent with custom model serialized to JSON
    new EventGridEvent(
        "ExampleEventSubject",
        "Example.EventType",
        "1.0",
        new CustomModel() { A = 5, B = true }),

    // EventGridEvent with custom model serialized to JSON using a custom serializer
    new EventGridEvent(
        "ExampleEventSubject",
        "Example.EventType",
        "1.0",
        myCustomDataSerializer.Serialize(new CustomModel() { A = 5, B = true })),
};

// Send the events
await client.SendEventsAsync(eventsList);

将 CloudEvents 发布到事件网格主题

使用 执行将事件发布到事件网格。EventGridPublisherClient 使用提供 SendEvents/SendEventsAsync 的方法将事件发布到主题。

// Example of a custom ObjectSerializer used to serialize the event payload to JSON
var myCustomDataSerializer = new JsonObjectSerializer(
    new JsonSerializerOptions()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    });

// Add CloudEvents to a list to publish to the topic
List<CloudEvent> eventsList = new List<CloudEvent>
{
    // CloudEvent with custom model serialized to JSON
    new CloudEvent(
        "/cloudevents/example/source",
        "Example.EventType",
        new CustomModel() { A = 5, B = true }),

    // CloudEvent with custom model serialized to JSON using a custom serializer
    new CloudEvent(
        "/cloudevents/example/source",
        "Example.EventType",
        myCustomDataSerializer.Serialize(new CustomModel() { A = 5, B = true }),
        "application/json"),

    // CloudEvents also supports sending binary-valued data
    new CloudEvent(
        "/cloudevents/example/binarydata",
        "Example.EventType",
        new BinaryData(Encoding.UTF8.GetBytes("This is treated as binary data")),
        "application/octet-stream")};

// Send the events
await client.SendEventsAsync(eventsList);

将事件网格事件发布到事件网格域

事件域是用于大量与同一应用程序相关的事件网格主题的管理工具。 可将其视为可包含数千个单独主题的元主题。 创建事件域时,将获得一个发布终结点,这与在事件网格中创建主题时类似。

若要将事件发布到事件域中的主题,请将事件推送到域的终结点,方法与使用自定义主题时相同。 唯一的区别是,必须指定要将事件传递到的主题。

// Add EventGridEvents to a list to publish to the domain
// Don't forget to specify the topic you want the event to be delivered to!
List<EventGridEvent> eventsList = new List<EventGridEvent>
{
    new EventGridEvent(
        "ExampleEventSubject",
        "Example.EventType",
        "1.0",
        "This is the event data")
    {
        Topic = "MyTopic"
    }
};

// Send the events
await client.SendEventsAsync(eventsList);

对于发送 CloudEvent,CloudEvent 源用作域主题:

List<CloudEvent> eventsList = new List<CloudEvent>();

for (int i = 0; i < 10; i++)
{
    CloudEvent cloudEvent = new CloudEvent(
        // the source is mapped to the domain topic
        $"Subject-{i}",
        "Microsoft.MockPublisher.TestEvent",
        "hello")
    {
        Id = $"event-{i}",
        Time = DateTimeOffset.Now
    };
    eventsList.Add(cloudEvent);
}

await client.SendEventsAsync(eventsList);

接收和反序列化事件

有几个不同的 Azure 服务充当 事件处理程序

注意:如果使用 Webhook 传送 事件网格架构,事件网格要求在 Webhook 终结点开始将事件传递到该终结点之前证明其所有权。 创建事件订阅时,事件网格会将订阅验证事件发送到终结点,如下所示。 在此处详细了解如何完成握手: Webhook 事件传递。 对于 CloudEvents 架构,服务使用 HTTP 选项方法验证连接。 在此处了解详细信息: CloudEvents 验证

将事件传递到事件处理程序后,我们可以将 JSON 有效负载反序列化为事件列表。

使用 EventGridEvent

// Parse the JSON payload into a list of events
EventGridEvent[] egEvents = EventGridEvent.ParseMany(BinaryData.FromStream(httpContent));

使用 CloudEvent

var bytes = await httpContent.ReadAsByteArrayAsync();
// Parse the JSON payload into a list of events
CloudEvent[] cloudEvents = CloudEvent.ParseMany(new BinaryData(bytes));

反序列化事件数据

从这里,可以通过对 属性调用ToObjectFromJson<T>()Data反序列化到特定类型来访问事件数据。 为了反序列化为正确的类型, EventType CloudEvents) Type 属性 (有助于区分不同的事件。 应使用泛型方法 ToObjectFromJson<T>()反序列化自定义事件数据。 还有一个扩展方法 ToObject<T>() ,该方法接受自定义 ObjectSerializer 以反序列化事件数据。

foreach (CloudEvent cloudEvent in cloudEvents)
{
    switch (cloudEvent.Type)
    {
        case "Contoso.Items.ItemReceived":
            // By default, ToObjectFromJson<T> uses System.Text.Json to deserialize the payload
            ContosoItemReceivedEventData itemReceived = cloudEvent.Data.ToObjectFromJson<ContosoItemReceivedEventData>();
            Console.WriteLine(itemReceived.ItemSku);
            break;
        case "MyApp.Models.CustomEventType":
            // One can also specify a custom ObjectSerializer as needed to deserialize the payload correctly
            TestPayload testPayload = cloudEvent.Data.ToObject<TestPayload>(myCustomSerializer);
            Console.WriteLine(testPayload.Name);
            break;
        case SystemEventNames.StorageBlobDeleted:
            // Example for deserializing system events using ToObjectFromJson<T>
            StorageBlobDeletedEventData blobDeleted = cloudEvent.Data.ToObjectFromJson<StorageBlobDeletedEventData>();
            Console.WriteLine(blobDeleted.BlobType);
            break;
    }
}

使用 TryGetSystemEventData()

如果主要需要系统事件,则打开 TryGetSystemEventData() 并使用模式匹配对单个事件执行操作可能更简洁。 如果事件不是系统事件,则 方法将返回 false,而 out 参数将为 null。

请注意,如果使用具有 EventType 值的自定义事件类型,该事件类型稍后由服务和 SDK 添加为系统事件,则 的 TryGetSystemEventData 返回值将从 更改为 falsetrue。 如果先发制人地为服务发送但尚未添加到 SDK 的事件创建自己的自定义事件,则可能会发生这种情况。 在这种情况下,最好在 属性上使用Data泛型ToObjectFromJson<T>方法,这样代码流就不会在升级后自动更改 (当然,你可能仍希望修改代码以使用新发布的系统事件模型,而不是自定义模型) 。

foreach (EventGridEvent egEvent in egEvents)
{
    // If the event is a system event, TryGetSystemEventData will return the deserialized system event
    if (egEvent.TryGetSystemEventData(out object systemEvent))
    {
        switch (systemEvent)
        {
            case SubscriptionValidationEventData subscriptionValidated:
                Console.WriteLine(subscriptionValidated.ValidationCode);
                break;
            case StorageBlobCreatedEventData blobCreated:
                Console.WriteLine(blobCreated.BlobType);
                break;
            // Handle any other system event type
            default:
                Console.WriteLine(egEvent.EventType);
                // we can get the raw Json for the event using Data
                Console.WriteLine(egEvent.Data.ToString());
                break;
        }
    }
    else
    {
        switch (egEvent.EventType)
        {
            case "MyApp.Models.CustomEventType":
                TestPayload deserializedEventData = egEvent.Data.ToObjectFromJson<TestPayload>();
                Console.WriteLine(deserializedEventData.Name);
                break;
            // Handle any other custom event type
            default:
                Console.Write(egEvent.EventType);
                Console.WriteLine(egEvent.Data.ToString());
                break;
        }
    }
}

疑难解答

服务响应

SendEvents() 从服务返回 HTTP 响应代码。 对于 RequestFailedException 任何不成功的请求,会作为服务响应引发 。 异常包含有关从服务返回的响应代码的信息。

反序列化事件数据

  • 如果事件数据不是有效的 JSON, JsonException 则在调用 ParseParseMany时将引发 。
  • 如果事件架构不对应于要反序列化为 (的类型(例如,调用 CloudEvent.Parse eventGridSchema 事件) ), ArgumentException 则会引发 。
  • 如果 Parse 对包含多个事件的数据调用 , ArgumentException 则会引发 。 ParseMany 应在此处改用 。

设置控制台日志记录

如果想要更深入地了解针对服务发出的请求,还可以轻松启用控制台记录

分布式跟踪

事件网格库支持现成分布跟踪。 根据有关分布式跟踪的 CloudEvents 规范指南,当分布式跟踪已启用时,该库会在 CloudEventExtensionAttributes 上设置 traceparenttracestate。 若要详细了解如何在应用程序中启用分布式跟踪,请参阅 Azure SDK 分布式跟踪文档

Kubernetes 上的事件网格

此库已在 Kubernetes 上使用 Azure Arc 进行测试和验证。

后续步骤

在此处查看更多 https://github.com/Azure/azure-sdk-for-net/blob/Azure.Messaging.EventGrid_4.20.0/sdk/eventgrid/Azure.Messaging.EventGrid/samples 事件网格客户端库的常见用法: 事件网格示例

贡献

本项目欢迎贡献和建议。 大多数贡献要求你同意贡献者许可协议 (CLA),并声明你有权(并且确实有权)授予我们使用你的贡献的权利。 有关详细信息,请访问 参与者许可协议

提交拉取请求时,CLA 机器人将自动确定你是否需要提供 CLA,并相应地修饰 PR(例如标签、注释)。 直接按机器人提供的说明操作。 只需使用 CLA 对所有存储库执行一次这样的操作。

此项目采用了 Microsoft 开放源代码行为准则。 有关详细信息,请参阅行为准则常见问题解答,或如果有任何其他问题或意见,请与 联系。

曝光数