将 CloudEvents v1.0 架构与事件网格配合使用Use CloudEvents v1.0 schema with Event Grid

除了采用默认事件架构的事件,Azure 事件网格本身还支持采用 CloudEvents v1.0 的 JSON 架构HTTP 协议绑定的事件。In addition to its default event schema, Azure Event Grid natively supports events in the JSON implementation of CloudEvents v1.0 and HTTP protocol binding. CloudEvents 是一种用于描述事件数据的开放规范CloudEvents is an open specification for describing event data.

CloudEvents 提供的常用事件架构适合发布和使用基于云的事件,因此可简化互操作性。CloudEvents simplifies interoperability by providing a common event schema for publishing and consuming cloud-based events. 可以通过此架构使用统一的工具、以标准方式路由和处理事件,以及以通用方式反序列化外部事件架构。This schema allows for uniform tooling, standard ways of routing and handling events, and universal ways of deserializing the outer event schema. 使用通用架构可以更轻松地跨平台集成工作。With a common schema, you can more easily integrate work across platforms.

CloudEvents 是由包括 Microsoft 在内的多个协作者通过 Cloud Native Computing Foundation 构建的。CloudEvents is being built by several collaborators, including Microsoft, through the Cloud Native Computing Foundation. 它目前的发布版本为 1.0。It's currently available as version 1.0.

本文介绍如何将 CloudEvents 架构与事件网格配合使用。This article describes how to use the CloudEvents schema with Event Grid.

CloudEvent 架构CloudEvent schema

下面是一个采用 CloudEvents 格式的 Azure Blob 存储事件示例:Here's an example of an Azure Blob Storage event in CloudEvents format:

{
    "specversion": "1.0",
    "type": "Microsoft.Storage.BlobCreated",  
    "source": "/subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Storage/storageAccounts/{storage-account}",
    "id": "9aeb0fdf-c01e-0131-0922-9eb54906e209",
    "time": "2019-11-18T15:13:39.4589254Z",
    "subject": "blobServices/default/containers/{storage-container}/blobs/{new-file}",
    "dataschema": "#",
    "data": {
        "api": "PutBlockList",
        "clientRequestId": "4c5dd7fb-2c48-4a27-bb30-5361b5de920a",
        "requestId": "9aeb0fdf-c01e-0131-0922-9eb549000000",
        "eTag": "0x8D76C39E4407333",
        "contentType": "image/png",
        "contentLength": 30699,
        "blobType": "BlockBlob",
        "url": "https://gridtesting.blob.core.chinacloudapi.cn/testcontainer/{new-file}",
        "sequencer": "000000000000000000000000000099240000000000c41c18",
        "storageDiagnostics": {
            "batchId": "681fe319-3006-00a8-0022-9e7cde000000"
        }
    }
}

有关可用字段及其类型和定义的详细说明,请参阅 CloudEvents v1.0For a detailed description of the available fields, their types, and definitions, see CloudEvents v1.0.

在 CloudEvents 架构和事件网格架构中传递的事件的标头值是相同的,但 content-type 除外。The headers values for events delivered in the CloudEvents schema and the Event Grid schema are the same except for content-type. 对于 CloudEvents 架构,该标头值为 "content-type":"application/cloudevents+json; charset=utf-8"For the CloudEvents schema, that header value is "content-type":"application/cloudevents+json; charset=utf-8". 对于事件网格架构,该标头值为 "content-type":"application/json; charset=utf-8"For the Event Grid schema, that header value is "content-type":"application/json; charset=utf-8".

为 CloudEvents 配置事件网格Configure Event Grid for CloudEvents

可以将事件网格用于 CloudEvents 架构中的事件的输入和输出。You can use Event Grid for both input and output of events in the CloudEvents schema. 下表说明了可能的转换:The following table describes the possible transformations:

事件网格资源Event Grid resource 输入架构Input schema 传递架构Delivery schema
系统主题System Topics 事件网格架构Event Grid schema 事件网格架构或 CloudEvent 架构Event Grid schema or CloudEvent schema
用户主题/域User Topics/Domains 事件网格架构Event Grid schema 事件网格架构Event Grid schema
用户主题/域User Topics/Domains CloudEvent 架构CloudEvent schema CloudEvent 架构CloudEvent schema
用户主题/域User Topics/Domains 自定义架构Custom schema 自定义架构、事件网格架构或 CloudEvent 架构Custom schema, Event Grid schema, or CloudEvent schema
PartnerTopicsPartnerTopics CloudEvent 架构CloudEvent schema CloudEvent 架构CloudEvent schema

对于所有事件架构,事件网格都要求在发布到事件网格主题时以及在创建事件订阅时进行验证。For all event schemas, Event Grid requires validation when you're publishing to an Event Grid topic and when you're creating an event subscription.

有关详细信息,请参阅事件网格安全性和身份验证For more information, see Event Grid security and authentication.

输入架构Input schema

在创建自定义主题时为自定义主题设置输入架构。You set the input schema for a custom topic when you create the custom topic.

对于 Azure CLI,请使用:For the Azure CLI, use:

az eventgrid topic create \
  --name <topic_name> \
  -l chinaeast \
  -g gridResourceGroup \
  --input-schema cloudeventschemav1_0

对于 PowerShell,请使用:For PowerShell, use:

New-AzEventGridTopic `
  -ResourceGroupName gridResourceGroup `
  -Location chinaeast `
  -Name <topic_name> `
  -InputSchema CloudEventSchemaV1_0

输出架构Output schema

在创建事件订阅时设置输出架构。You set the output schema when you create the event subscription.

对于 Azure CLI,请使用:For the Azure CLI, use:

topicID=$(az eventgrid topic show --name <topic-name> -g gridResourceGroup --query id --output tsv)

az eventgrid event-subscription create \
  --name <event_subscription_name> \
  --source-resource-id $topicID \
  --endpoint <endpoint_URL> \
  --event-delivery-schema cloudeventschemav1_0

对于 PowerShell,请使用:For PowerShell, use:

$topicid = (Get-AzEventGridTopic -ResourceGroupName gridResourceGroup -Name <topic-name>).Id

New-AzEventGridSubscription `
  -ResourceId $topicid `
  -EventSubscriptionName <event_subscription_name> `
  -Endpoint <endpoint_URL> `
  -DeliverySchema CloudEventSchemaV1_0

目前,在以 CloudEvents 架构传递事件时,无法为 Azure Functions 应用使用事件网格触发器。Currently, you can't use an Event Grid trigger for an Azure Functions app when the event is delivered in the CloudEvents schema. 使用 HTTP 触发器。Use an HTTP trigger. 有关实现在 CloudEvents 架构中接收事件的 HTTP 触发器的示例,请参阅将 CloudEvents 与 Azure Functions 配合使用For examples of implementing an HTTP trigger that receives events in the CloudEvents schema, see Using CloudEvents with Azure Functions.

使用 CloudEvents v1.0 验证终结点Endpoint validation with CloudEvents v1.0

如果熟悉事件网格,你可能会了解用于防止滥用的终结点验证握手。If you're already familiar with Event Grid, you might be aware of the endpoint validation handshake for preventing abuse. CloudEvents v1.0 使用 HTTP OPTIONS 方法来实现自己的滥用防护语义CloudEvents v1.0 implements its own abuse protection semantics by using the HTTP OPTIONS method. 若要了解有关详细信息,请参阅适用于事件传递的 HTTP 1.1 Webhook - 版本 1.0To read more about it, see HTTP 1.1 Web Hooks for event delivery - Version 1.0. 使用 CloudEvents 架构进行输出时,事件网格将使用 CloudEvents v1.0 滥用防护取代事件网格验证事件机制。When you use the CloudEvents schema for output, Event Grid uses the CloudEvents v1.0 abuse protection in place of the Event Grid validation event mechanism.

与 Azure Functions 配合使用Use with Azure Functions

Azure Functions 事件网格绑定本身不支持 CloudEvents,因此,HTTP 触发的函数被用来读取 CloudEvents 消息。The Azure Functions Event Grid binding doesn't natively support CloudEvents, so HTTP-triggered functions are used to read CloudEvents messages. 使用 HTTP 触发器来读取 CloudEvents 时,必须编写代码来指定事件网格触发器自动执行的操作:When you use an HTTP trigger to read CloudEvents, you have to write code for what the Event Grid trigger does automatically:

  • 将验证响应发送到订阅验证请求Sends a validation response to a subscription validation request
  • 针对请求正文中包含的事件数组的每个元素调用该函数一次Invokes the function once per element of the event array contained in the request body

有关用于在本地调用函数或者在 Azure 中运行函数的 URL 的信息,请参阅 HTTP 触发器绑定参考文档For information about the URL to use for invoking the function locally or when it runs in Azure, see the HTTP trigger binding reference documentation.

以下 HTTP 触发器的示例 C# 代码可模拟事件网格触发器的行为。The following sample C# code for an HTTP trigger simulates Event Grid trigger behavior. 将此示例用于以 CloudEvents 架构传递的事件。Use this example for events delivered in the CloudEvents schema.

[FunctionName("HttpTrigger")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", "options", Route = null)]HttpRequestMessage req, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");
    if (req.Method == HttpMethod.Options)
    {
        // If the request is for subscription validation, send back the validation code
        
        var response = req.CreateResponse(HttpStatusCode.OK);
        response.Headers.Add("Webhook-Allowed-Origin", "eventgrid.azure.cn");

        return response;
    }

    var requestmessage = await req.Content.ReadAsStringAsync();
    var message = JToken.Parse(requestmessage);

    // The request isn't for subscription validation, so it's for an event.
    // CloudEvents schema delivers one event at a time.
    log.LogInformation($"Source: {message["source"]}");
    log.LogInformation($"Time: {message["eventTime"]}");
    log.LogInformation($"Event data: {message["data"].ToString()}");

    return req.CreateResponse(HttpStatusCode.OK);
}

以下 HTTP 触发器的示例 JavaScript 代码可模拟事件网格触发器的行为。The following sample JavaScript code for an HTTP trigger simulates Event Grid trigger behavior. 将此示例用于以 CloudEvents 架构传递的事件。Use this example for events delivered in the CloudEvents schema.

module.exports = function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');
    
    if (req.method == "OPTIONS") {
        // If the request is for subscription validation, send back the validation code
        
        context.log('Validate request received');
        context.res = {
            status: 200,
            headers: {
                'Webhook-Allowed-Origin': 'eventgrid.azure.cn',
            },
         };
    }
    else
    {
        var message = req.body;
        
        // The request isn't for subscription validation, so it's for an event.
        // CloudEvents schema delivers one event at a time.
        var event = JSON.parse(message);
        context.log('Source: ' + event.source);
        context.log('Time: ' + event.eventTime);
        context.log('Data: ' + JSON.stringify(event.data));
    }
 
    context.done();
};

后续步骤Next steps