.net core 如何将EventProcessorClient配置为仅读取特定分区键(而不是分区id)的事件?
我有一个带有2个分区的事件中心,并使用以下代码使用不同的分区键(基于上的文档)向它发送事件。我正在使用.NET的Azure.Messaging.EventHubs库(使用.NET core 3.1) 如您所见,我发送了第一批带有2个事件(使用分区键作为MyPartitionA),第二批带有2个事件(使用分区键作为MyPartitionB)。有趣的是,来自两个分区键的事件进入了同一个分区(即事件中心上的分区0) 在接收端,我正在尝试使用位于的代码示例,如下所示(我正在使用.NET的Azure.Messaging.EventHubs.Processor库。) 然而,我在上面的代码中找不到只接收给定分区(比如MyPartitionA)的事件而不接收其他分区(比如MyPartitionB)的事件的方法.net core 如何将EventProcessorClient配置为仅读取特定分区键(而不是分区id)的事件?,.net-core,azure-eventhub,azure-sdk-.net,.net Core,Azure Eventhub,Azure Sdk .net,我有一个带有2个分区的事件中心,并使用以下代码使用不同的分区键(基于上的文档)向它发送事件。我正在使用.NET的Azure.Messaging.EventHubs库(使用.NET core 3.1) 如您所见,我发送了第一批带有2个事件(使用分区键作为MyPartitionA),第二批带有2个事件(使用分区键作为MyPartitionB)。有趣的是,来自两个分区键的事件进入了同一个分区(即事件中心上的分区0) 在接收端,我正在尝试使用位于的代码示例,如下所示(我正在使用.NET的Azure.Me
EventHubs是一种高吞吐量的持久流,提供流级语义(与服务总线相比) 现在来回答您的问题,您希望根据事件的属性筛选事件—事件级操作—不是流级操作 没有直接的方法来实现您的需求 这种方法是为自己实现定制解决方案——从EventHub(事件流)中提取事件,并有一个中间进程t0按PartitionKey进行过滤,然后将它们推送到另一个事件中心或替代机制,以便相应地使用它 或者,如果您正在考虑使用服务总线(如果这符合您的要求),则您可以参考以下内容: 分区键属性将用于标识分区 当会话id为时,消息必须存储在队列中 未设置消息的属性 您可以使用AcceptMessageSession([PartitionKey])从特定分区键或会话ID接收消息 参考:
qc=您不能使用SDK中的任何客户端读取基于分区键的事件 分区键是一个合成概念,在事件发布后不会保留该概念。当您使用分区键发布时,该键将被散列,结果值用于选择要将事件路由到的分区;其目的是确保相关事件路由到同一个分区,但不需要了解选择了哪个分区,也不提供任何公平分配的保证 要完成您希望执行的筛选,您需要将分区键存储为事件上的,然后将该值用作
ProcessEventAsync
处理程序中的筛选器。请注意,您将从所有分区接收所有事件-这是EventProcessorClient
的主要目标
我认为我们对应用程序场景的上下文了解不够,无法帮助确定最佳方法,但根据我们所知,我建议考虑另一种方法。由于您似乎需要显式地读取一组事件,因此使用已知分区的Id(而不是键)发布到该分区可能会有所帮助。然后,您将能够使用该方法以独占方式从该分区读取事件。当然,这需要您明确控制在应用程序中发布其他事件的位置,以确保它们被路由到第二个分区。什么是qc,以及它与上面代码中的EventProcessorClient有何关系?你能详细解释一下吗?@Raghu-有点混乱。更新了我的答案。:)
await using (var producer = new EventHubProducerClient(connectionString, eventHubName))
{
using EventDataBatch eventBatch = await producer.CreateBatchAsync(new CreateBatchOptions() { PartitionKey = "MyPartitionA" });
eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("First")));
eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("Second")));
await produce.SendAsync(eventBatch);
using EventDataBatch eventBatch2 = await producer.CreateBatchAsync(new CreateBatchOptions() { PartitionKey = "MyPartitionB" });
eventBatch2.TryAdd(new EventData(Encoding.UTF8.GetBytes("Third")));
eventBatch2.TryAdd(new EventData(Encoding.UTF8.GetBytes("Fourth")));
await producer.SendAsync(eventBatch2);
}
async Task processEventHandler(ProcessEventArgs eventArgs)
{
try
{
// Perform the application-specific processing for an event
await DoSomethingWithTheEvent(eventArgs.Partition, eventArgs.Data);
}
catch
{
// Handle the exception from handler code
}
}
async Task processErrorHandler(ProcessErrorEventArgs eventArgs)
{
try
{
// Perform the application-specific processing for an error
await DoSomethingWithTheError(eventArgs.Exception);
}
catch
{
// Handle the exception from handler code
}
}
private async Task ProcessUntilCanceled(CancellationToken cancellationToken)
{
var storageClient = new BlobContainerClient(storageConnectionString, blobContainerName);
var processor = new EventProcessorClient(storageClient, consumerGroup, eventHubsConnectionString, eventHubName);
processor.ProcessEventAsync += processEventHandler;
processor.ProcessErrorAsync += processErrorHandler;
await processor.StartProcessingAsync();
try
{
while (!cancellationToken.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromSeconds(1));
}
await processor.StopProcessingAsync();
}
finally
{
// To prevent leaks, the handlers should be removed when processing is complete
processor.ProcessEventAsync -= processEventHandler;
processor.ProcessErrorAsync -= processErrorHandler;
}
}
var partitionlistener = qc.AcceptMessageSession("MyPartitionA");
var message = partitionlistener.Receive();