将大于256KB的事件推送到Azure EventHub

将大于256KB的事件推送到Azure EventHub,azure,azureservicebus,azure-eventhub,Azure,Azureservicebus,Azure Eventhub,我正在使用Azure事件中心。我计划发送事件并使用SendBatchAsync。我发现Event Hub的限制为256KB(无论是单独发送还是批量发送) 那么,如果我的数据>256KB,处理这个问题的最佳实践是什么?我们是否应该单独发送消息(这将保证它小于256KB) 另外,如何将事件拆分为256KB的块并发送到事件中心? 我查看了Azure文档,看到他们建议使用EventHubClient.CreateBatch,但我没有看到足够的示例。有人能提供一些模型或示例,或者我们最终如何拆分为256K

我正在使用Azure事件中心。我计划发送事件并使用SendBatchAsync。我发现Event Hub的限制为256KB(无论是单独发送还是批量发送)

那么,如果我的数据>256KB,处理这个问题的最佳实践是什么?我们是否应该单独发送消息(这将保证它小于256KB)

另外,如何将事件拆分为256KB的块并发送到事件中心? 我查看了Azure文档,看到他们建议使用EventHubClient.CreateBatch,但我没有看到足够的示例。有人能提供一些模型或示例,或者我们最终如何拆分为256KB和SendBatchAsync所需的步骤吗

以下是我所做的(但不要考虑256KB的限制)


不要试图在多条消息中分块单个有效负载,因为事件不能保证按顺序到达,可能会在不同的分区中结束,可能会间隔一段时间到达,并且可以独立于“总线”删除,因此跟踪和重构变得极为困难。这在规模上变得更具挑战性

<强>选项1:< /强>如果您的有效载荷是文本/JSON,并且您的消息大小不大于256KB,请考虑压缩有效载荷。您可以从中了解大小结果。如果您的负载中有大量空白(例如,对于JSON),您也可以不压缩

选项2:而是将有效负载存储在外部存储中(比如DocumentDB或Blob存储)


在事件中发送对有效负载的引用。这使您的事件保持精简,但您的消费者需要了解如何检索有效负载。一个简单的方法是将链接作为有效URI呈现给有效负载,显然您可能需要考虑与您的事件集线器访问策略相关的有效载荷存储中的认证和授权,以使其保持光滑。p> 下面是一个关于如何在不超过256KB限制的情况下使用send batch的示例。 代码来自此回购协议()

//
///此类包含该类的扩展方法。
/// 
公共静态类EventHubClientExtensions
{
private const string EventDataListCannotBeNullOrEmpty=“eventDataEnumerable参数不能为null或空。”;
私有常量字符串SendPartitionedBatchFormat=“[EventHubClient.SendPartitionedBatch]批发送:BatchSizeInBytes=[{0}]MessageCount=[{1}]”;
私有常量字符串SendPartitionedBatchAsyncFormat=“[EventHubClient.SendPartitionedBatchAsync]批发送:BatchSizeInBytes=[{0}]MessageCount=[{1}]”;
私有常量int MaxBathSizeInBytes=262144;
/// 
///异步向同一分区发送一批事件数据。
///批处理中的所有事件数据需要在Partitionkey属性中具有相同的值。
///如果批量大于最大批量,
///该方法将原始批次划分为多个批次,
///每个都比最大批量小。
/// 
///当前对象。
///包含事件数据实例的IEnumerable对象。
///true可导致写入消息;否则为false。
///异步操作。
公共静态异步任务SendPartitionedBatchAsync(此EventHubClient EventHubClient,IEnumerable消息,bool trace=false)
{
var eventDataList=作为IList的消息??messages.ToList();
if(messages==null | |!eventDataList.Any())
{
抛出新ArgumentNullException(EventDataListCannotBeNullOrEmpty);
}
var batchList=新列表();
长批量大小=0;
foreach(eventDataList中的var eventData)
{
if((batchSize+eventData.SerializedSizeInBytes)>MaxBathSizeInBytes)
{
//发送当前批次
等待eventHubClient.SendBatchAsync(批处理列表);
WriteLineIf(Trace,string.Format(SendPartitionedBatchAsyncFormat,batchSize,batchList.Count));
//初始化新批
batchList=新列表{eventData};
batchSize=eventData.SerializedSizeInBytes;
}
其他的
{
//将EventData添加到当前批处理中
batchList.Add(事件数据);
batchSize+=eventData.SerializedSizeInBytes;
}
}
//最后一批发送到循环外部
等待eventHubClient.SendBatchAsync(批处理列表);
WriteLineIf(Trace,string.Format(SendPartitionedBatchAsyncFormat,batchSize,batchList.Count));
}
/// 
///异步向同一分区发送一批事件数据。
///批处理中的所有事件数据需要在Partitionkey属性中具有相同的值。
///如果批量大于最大批量,
///该方法将原始批次划分为多个批次,
///每个都比最大批量小。
/// 
///当前对象。
///包含事件数据实例的IEnumerable对象。
///true可导致写入消息;否则为false。
public static void SendPartitionedBatch(此EventHubClient EventHubClient,IEnumerable messages,
bool trace=false)
{
var eventDataList=作为IList的消息??messages.ToList();
if(messages==null | |!eventDataList.Any())
{
抛出新ArgumentNullException(EventDataListCannotBeNullOrEmpty);
}
var batchList=新列表();
长批量大小=0;
foreach(eventDataList中的var eventData)
{
if((batchSize+eventData.SerializedSizeInBytes)>MaxBathSizeInBytes)
{
//发送当前批次
eventHubClient.SendBatch(批处理列表);
Trace.WriteLineIf(t
await myEventHubClient.SendBatchAsync(
    events.Select( 
        iEvent =>
            new EventData(
                Encoding.UTF8.GetBytes(JsonConvert.SerializeObject( iEvent ) ) ) ) );
/// <summary>
/// This class contains extensions methods for the <see cref="EventHubClient"/> class.
/// </summary>
public static class EventHubClientExtensions
{
    private const string EventDataListCannotBeNullOrEmpty = "The eventDataEnumerable parameter cannot be null or empty.";
    private const string SendPartitionedBatchFormat = "[EventHubClient.SendPartitionedBatch] Batch Sent: BatchSizeInBytes=[{0}] MessageCount=[{1}]";
    private const string SendPartitionedBatchAsyncFormat = "[EventHubClient.SendPartitionedBatchAsync] Batch Sent: BatchSizeInBytes=[{0}] MessageCount=[{1}]";
    private const int MaxBathSizeInBytes = 262144;

    /// <summary>
    /// Asynchronously sends a batch of event data to the same partition.
    /// All the event data in the batch need to have the same value in the Partitionkey property.
    /// If the batch size is greater than the maximum batch size, 
    /// the method partitions the original batch into multiple batches, 
    /// each smaller in size than the maximum batch size.
    /// </summary>
    /// <param name="eventHubClient">The current <see cref="EventHubClient"/> object.</param>
    /// <param name="messages">An IEnumerable object containing event data instances.</param>
    /// <param name="trace">true to cause a message to be written; otherwise, false.</param>
    /// <returns>The asynchronous operation.</returns>
    public static async Task SendPartitionedBatchAsync(this EventHubClient eventHubClient, IEnumerable<EventData> messages, bool trace = false)
    {
        var eventDataList = messages as IList<EventData> ?? messages.ToList();
        if (messages == null || !eventDataList.Any())
        {
            throw new ArgumentNullException(EventDataListCannotBeNullOrEmpty);
        }

        var batchList = new List<EventData>();
        long batchSize = 0;

        foreach (var eventData in eventDataList)
        {
            if ((batchSize + eventData.SerializedSizeInBytes) > MaxBathSizeInBytes)
            {
                // Send current batch
                await eventHubClient.SendBatchAsync(batchList);
                Trace.WriteLineIf(trace, string.Format(SendPartitionedBatchAsyncFormat, batchSize, batchList.Count));

                // Initialize a new batch
                batchList = new List<EventData> { eventData };
                batchSize = eventData.SerializedSizeInBytes;
            }
            else
            {
                // Add the EventData to the current batch
                batchList.Add(eventData);
                batchSize += eventData.SerializedSizeInBytes;
            }
        }
        // The final batch is sent outside of the loop
        await eventHubClient.SendBatchAsync(batchList);
        Trace.WriteLineIf(trace, string.Format(SendPartitionedBatchAsyncFormat, batchSize, batchList.Count));
    }

    /// <summary>
    /// Asynchronously sends a batch of event data to the same partition.
    /// All the event data in the batch need to have the same value in the Partitionkey property.
    /// If the batch size is greater than the maximum batch size, 
    /// the method partitions the original batch into multiple batches, 
    /// each smaller in size than the maximum batch size.
    /// </summary>
    /// <param name="eventHubClient">The current <see cref="EventHubClient"/> object.</param>
    /// <param name="messages">An IEnumerable object containing event data instances.</param>
    /// <param name="trace">true to cause a message to be written; otherwise, false.</param>
    public static void SendPartitionedBatch(this EventHubClient eventHubClient, IEnumerable<EventData> messages,
        bool trace = false)
    {
        var eventDataList = messages as IList<EventData> ?? messages.ToList();
        if (messages == null || !eventDataList.Any())
        {
            throw new ArgumentNullException(EventDataListCannotBeNullOrEmpty);
        }

        var batchList = new List<EventData>();
        long batchSize = 0;

        foreach (var eventData in eventDataList)
        {
            if ((batchSize + eventData.SerializedSizeInBytes) > MaxBathSizeInBytes)
            {
                // Send current batch
                eventHubClient.SendBatch(batchList);
                Trace.WriteLineIf(trace, string.Format(SendPartitionedBatchAsyncFormat, batchSize, batchList.Count));

                // Initialize a new batch
                batchList = new List<EventData> { eventData };
                batchSize = eventData.SerializedSizeInBytes;
            }
            else
            {
                // Add the EventData to the current batch
                batchList.Add(eventData);
                batchSize += eventData.SerializedSizeInBytes;
            }
        }
        // The final batch is sent outside of the loop
        eventHubClient.SendBatch(batchList);
        Trace.WriteLineIf(trace, string.Format(SendPartitionedBatchFormat, batchSize, batchList.Count));
    }
}