![](/img/trans.png)
[英]Hubs not receiving any messages when using MassTransit SignalR backplane
[英]How to disable other partitions to stop receiving messages when one partition is active in Azure event hubs
我有一個安裝在 3 個不同服務器上的應用程序。這個應用程序訂閱了一個事件中心。 此事件中心有 8 個分區。 所以當我在所有 3 台機器上啟動我的應用程序時,所有分區在所有 3 台機器上隨機初始化。
說是這樣的:
VM1:分區 0,1,2
VM2:分區 3,4
VM3:分區 5、6、7
所有這些分區都在不斷地接收消息。 這些消息需要一個接一個地處理。 現在我的要求是,在一台機器/服務器中,我想一次只接收一條消息(無論初始化了多少個分區)。 VM1、VM2、VM3 也可以並行運行。
一個場景是,在一台機器上,比如 VM1,我通過分區 0 收到了一條消息。現在正在處理該消息,通常需要 15 分鍾。 在這 15 分鍾內,我不希望分區 1 或分區 2 在前一個完成之前接收任何新消息。 一旦前面的消息處理完成,那么 3 個分區中的任何一個都准備好接收新消息。 一旦任何分區收到另一條消息,其他分區不應收到任何消息。
我使用的代碼是這樣的:
public class SimpleEventProcessor : IEventProcessor
{
public Task CloseAsync(PartitionContext context, CloseReason reason)
{
Console.WriteLine($"Processor Shutting Down. Partition '{context.PartitionId}', Reason: '{reason}'.");
return Task.CompletedTask;
}
public Task OpenAsync(PartitionContext context)
{
Console.WriteLine($"SimpleEventProcessor initialized. Partition: '{context.PartitionId}'");
return Task.CompletedTask;
}
public Task ProcessErrorAsync(PartitionContext context, Exception error)
{
Console.WriteLine($"Error on Partition: {context.PartitionId}, Error: {error.Message}");
return Task.CompletedTask;
}
public Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
{
foreach (var eventData in messages)
{
var data = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count);
Console.WriteLine($"Message received. Partition: '{context.PartitionId}', Data: '{data}'");
DoSomethingWithMessage(); // typically takes 15-20 mins to finish this method.
}
return context.CheckpointAsync();
}
}
這可能嗎?
PS:我必須使用事件中心,別無選擇。
您可以通過對靜態鎖對象進行互斥來實現這一點。
public Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
{
lock (lockObj)
{
foreach (var eventData in messages)
{
var data = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count);
Console.WriteLine($"Message received. Partition: '{context.PartitionId}', Data: '{data}'");
DoSomethingWithMessage(); // typically takes 15-20 mins to finish this method.
}
return context.CheckpointAsync();
}
}
不要忘記將 EventProcessorOptions.MaxBatchSize 設置為 1,如下所示。
var epo = new EventProcessorOptions
{
MaxBatchSize = 1
};
await eventProcessorHost.RegisterEventProcessorAsync<MyProcessorHost>(epo);
帶有下游代理的完整處理器代碼。
public class SampleEventProcessor : IEventProcessor
{
public Task OpenAsync(PartitionContext context)
{
Console.WriteLine($"Opened partition {context.PartitionId}");
return Task.FromResult<object>(null);
}
public Task CloseAsync(PartitionContext context, CloseReason reason)
{
Console.WriteLine($"Closed partition {context.PartitionId}");
return Task.FromResult<object>(null);
}
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
{
foreach (var eventData in messages)
{
// Process the mesasage in downstream agent.
await DownstreamAgent.ProcessEventAsync(eventData);
// Checkpoint current position.
await context.CheckpointAsync();
}
}
public Task ProcessErrorAsync(PartitionContext context, Exception error)
{
Console.WriteLine($"Partition {context.PartitionId} - {error.Message}");
return Task.CompletedTask;
}
}
public class DownstreamAgent
{
const int DegreeOfParallelism = 1;
static SemaphoreSlim threadSemaphore = new SemaphoreSlim(DegreeOfParallelism, DegreeOfParallelism);
public static async Task ProcessEventAsync(EventData message)
{
// Wait for a spot so this message can get processed.
await threadSemaphore.WaitAsync();
try
{
// Process the message here
var data = Encoding.UTF8.GetString(message.Body.Array);
Console.WriteLine(data);
}
finally
{
// Release the semaphore here so that next message waiting can be processed.
threadSemaphore.Release();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.