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

通过 Event Grid 触发自定义通知事件

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2020年6月7日

CPOL

3分钟阅读

viewsIcon

7883

您的微服务或函数应用如何通知其他应用其操作。

引言

通知是一种应用程序(或微服务或函数)可以向外界公开事件的方式,告诉他们“我已完成 x,您可能对此感兴趣”。

当通过事件网格发送通知时,可以添加订阅者来响应此通知,并且可以使用事件网格的高级筛选和路由功能,通过组合较小的组件和路由规则来构建复杂的系统。

背景

有关事件网格提供的所有功能的概述,我建议您查看 此概述。

在设计基于通知事件的系统时,我建议使用诸如 事件风暴事件建模 之类的技术。

构建要发送的通知消息

您的系统将发出的每种自定义通知消息类型都应填充 Microsoft.Azure.EventGrid.Models.EventGridData 的一个实例。此类定义以下属性

  • public string Id { get; set; }
  • public DateTime EventTime { get; set; }
  • public string DataVersion { get; set; }
  • public string Topic { get; set; }
  • public string Subject { get; set; }
  • public object Data { get; set; }
  • public string EventType { get; set; }

ID

这是消息的唯一标识符,可用于重复数据删除。如果您的应用程序没有自己唯一标识消息的方式,则将其设置为新的 GUID 是有效的。

EventTime

应将其设置为事件发生的时间。对于分布式系统,我建议使用 UTC 作为通用时间格式。

DataVersion

设置此版本号以指示您发送的消息有效负载的版本。每当您更改数据有效负载的属性时,都应增加此版本号,并将消息有效负载定义存储在源代码控制系统中或作为其他应用程序可以使用的库。

EventType

应将其设置为唯一标识已发生事件的字符串。您可以在事件类型中使用点来限定域 - 例如,添加新用户可能会触发一个事件:[Application].[Domain].UserAdded,以便可以将其与添加到不同应用程序或域的用户区分开来。

主题

通常将其设置为指示为谁或什么发送了通知。您可以使用路径分隔符来限定域 - 例如,在上述用户添加通知中,主题可以是 [Application]/[Domain]/[User Identifier]。

Data

这是您通知消息的有效负载所在的位置。您可以在此处放置任何可以序列化为 JSON 的对象,但是整个消息限制为 64KB,因此,如果您有大量数据,最好将其保存到公共 Blob 存储并发送 URI 在事件数据中。

事件网格确实允许按消息内容进行筛选。如果您这样做,最好保持数据内容较小。

发送通知消息

为了通过事件网格传输消息,您需要知道事件网格端点(通知消息发布到的位置)和用于证明您有权发布到该端点的访问密钥。通常,这些信息存储在应用程序的配置设置中,而不是硬编码的。

        public HttpMessageHandler HttpMessageHandler
        {
            get => httpMessageHandler;
            set
            {
                httpClient?.Dispose();
                httpMessageHandler = value;
                httpClient = new HttpClient(httpMessageHandler);
                httpClient.DefaultRequestHeaders.Add("aeg-sas-key", this.eventGridKeyValue);
            }
        }

除此之外,最好指定“重试计数”(如果通知失败,应尝试的次数)和“重试间隔”(两次重试之间等待的时间)。

要发送事件网格消息,我们需要将其转换为 JSON,然后将其发送到事件网格端点。

        private async Task SendNotificationAsync(
                EventGridEvent[] eventGridEventArray)
        {
            string json = JsonConvert.SerializeObject(eventGridEventArray);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpResponseMessage result = null;
            try
            {
                result = await httpClient.PostAsync(this.eventGridTopicEndpoint, content);
            }
            catch (Exception e)
            {
                if (null != _logger )
                {
                    _logger.LogError(e.Message);  
                }
                return;
            }

            using (result)
            {
                var body = await result.Content.ReadAsStringAsync();
                if (result.IsSuccessStatusCode)
                {
                    // Successfully sent the notification...
                    if (null != _logger)
                    {
                        _logger.LogInformation($"Sent notification via 
                                              {this.eventGridTopicEndpoint}" );
                    }
                }
                else
                {
                    // Failed to send the eventgrid notification...
                    if (null != _logger)
                    {
                        _logger.LogError($"Failed to send notification - 
                                        {result.StatusCode} {result.Content}");
                    }
                }
            }
        }

关注点

事件网格 提供所谓的“至少一次”消息传递。这意味着可能(并且您需要为此进行编码)会多次收到消息。

这可以通过基于唯一消息标识符对消息进行重复数据删除,或者通过使您的通知消息处理具有幂等性,以使消息的多个副本不会产生任何额外的影响来实现。

历史

  • 2020年6月7日:初稿
© . All rights reserved.