Asp.net core 在ASP.Net Core中处理EventHub使用者组的事件时忽略旧事件

Asp.net core 在ASP.Net Core中处理EventHub使用者组的事件时忽略旧事件,asp.net-core,azure-eventhub,Asp.net Core,Azure Eventhub,我有一个使用ASP.Net Core 3.1的API,它使用Azure.Messaging.EventHubs和Azure.Messaging.EventHubs.Processor从消费者组获取事件,然后将它们发送到信号器中心。处理器仅在有用户连接到集线器时运行,并在最后一个用户断开连接更新BlobStorage中的检查点时停止 每个事件的当前处理逻辑:如果DateTime.UtcNow和事件时间戳之间的时间差(以分钟为单位)小于2,则它将事件发送到信号集线器,仅此而已 问题如下:有时会有很长

我有一个使用ASP.Net Core 3.1的API,它使用
Azure.Messaging.EventHubs
Azure.Messaging.EventHubs.Processor
从消费者组获取事件,然后将它们发送到信号器中心。处理器仅在有用户连接到集线器时运行,并在最后一个用户断开连接更新BlobStorage中的检查点时停止

每个事件的当前处理逻辑:如果DateTime.UtcNow和事件时间戳之间的时间差(以分钟为单位)小于2,则它将事件发送到信号集线器,仅此而已

问题如下:有时会有很长一段时间,
EventProcessorClient
停止,许多事件保留在EventHub中,导致它等待很长时间,同时缓慢地赶上最近的事件,直到信号器Hub再次开始接收它们。处理器处理最新事件的时间太长,特别是在考虑每分钟接收数百个事件时

例如,是否有一种方法可以在启动处理器之前手动移动检查点?或者只获取最后X分钟的事件?也许是另一个想法/解决方案

附言:对于这个消费群体,我不喜欢超过2到5分钟的活动

PS2:在EventHub中配置的保留时间为1天

守则:

/* properties and stuff */
// Constructor
public BusEventHub(ILogger<BusEventHub> logger, IConfiguration configuration, IHubContext<BusHub> hubContext) {
    _logger = logger;
    Configuration = configuration;
    _busExcessHub = hubContext;

    /* Connection strings and stuff */

    // Create a blob container client that the event processor will use 
    storageClient = new BlobContainerClient(this.blobStorageConnectionString, this.blobContainerName);

    // Create an event processor client to process events in the event hub
    processor = new EventProcessorClient(storageClient, consumerGroup, this.ehubNamespaceConnectionString, this.eventHubName);

    // Register handlers for processing events and handling errors
    processor.ProcessEventAsync += ProcessEventHandler;
    processor.ProcessErrorAsync += ProcessErrorHandler;
}

public async Task Start() {
    _logger.LogInformation($"Starting event processing for EventHub {eventHubName}");
    await processor.StartProcessingAsync();
}

public async Task Stop() {
    if (BusHubUserHandler.ConnectedIds.Count < 2) {
        _logger.LogInformation($"Stopping event processing for EventHub {eventHubName}");
        await processor.StopProcessingAsync();
    } else {
        _logger.LogDebug("There are still other users connected");
    }
}

private async Task ProcessEventHandler(ProcessEventArgs eventArgs) {
    try {
        string receivedEvent = Encoding.UTF8.GetString(eventArgs.Data.Body.ToArray());
        _logger.LogDebug($"Received event: {receivedEvent}");

        BusExcessMinified busExcess = BusExcessMinified.FromJson(receivedEvent);
        double timeDiff = (DateTime.UtcNow - busExcess.Timestamp).TotalMinutes;

        if (timeDiff < 2) {
            string responseEvent = busExcess.ToJson();
            _logger.LogDebug($"Sending message to BusExcess Hub: {responseEvent}");
            await _busExcessHub.Clients.All.SendAsync("UpdateBuses", responseEvent);
        }

        _logger.LogDebug("Update checkpoint in the blob storage"); // So that the service receives only new events the next time it's run
        await eventArgs.UpdateCheckpointAsync(eventArgs.CancellationToken);
    } catch (TaskCanceledException) {
        _logger.LogInformation("The EventHub event processing was stopped");
    } catch (Exception e) {
        _logger.LogError($"Exception: {e}");
    }
}

/* ProcessErrorHandler */
/*属性和内容*/
//建造师
公共总线事件中心(ILogger记录器、IConfiguration配置、IHubContext hubContext){
_记录器=记录器;
配置=配置;
_busExcessHub=hubContext;
/*连接字符串和其他东西*/
//创建事件处理器将使用的blob容器客户端
storageClient=new BlobContainerClient(this.blobStorageConnectionString,this.blobContainerName);
//创建事件处理器客户端以处理事件中心中的事件
processor=新的EventProcessorClient(storageClient、consumerGroup、this.ehubNamespaceConnectionString、this.eventHubName);
//注册处理程序以处理事件和处理错误
processor.ProcessEventAsync+=ProcessEventHandler;
processor.ProcessErrorAsync+=ProcessErrorHandler;
}
公共异步任务启动(){
_logger.LogInformation($“正在为EventHub{eventHubName}启动事件处理”);
等待处理器。StartProcessingAsync();
}
公共异步任务停止(){
if(BusHubUserHandler.ConnectedIds.Count<2){
_logger.LogInformation($“正在停止EventHub{eventHubName}的事件处理”);
等待处理器。停止处理同步();
}否则{
_logger.LogDebug(“仍有其他用户连接”);
}
}
专用异步任务ProcessEventHandler(ProcessEventArgs eventArgs){
试一试{
string receivedEvent=Encoding.UTF8.GetString(eventArgs.Data.Body.ToArray());
_LogDebug($“已接收事件:{receivedEvent}”);
BusExcessMinified busExcess=BusExcessMinified.FromJson(receivedEvent);
double timeDiff=(DateTime.UtcNow-BusOversex.Timestamp).TotalMinutes;
如果(时间差<2){
字符串responseEvent=BusOverse.ToJson();
_LogDebug($“向总线中心发送消息:{responseEvent}”);
wait_busexesshub.Clients.All.SendAsync(“updateBuuse”,responseEvent);
}
_logger.LogDebug(“更新blob存储中的检查点”);//以便服务下次运行时只接收新事件
等待eventArgs.UpdateCheckpointAsync(eventArgs.CancellationToken);
}捕获(TaskCanceledException){
_logger.LogInformation(“EventHub事件处理已停止”);
}捕获(例外e){
_logger.LogError($“异常:{e}”);
}
}
/*ProcessErrorHandler*/

可以在分区初始化时请求其初始位置,这将允许您指定排队时间作为起点。这说明了细节。需要注意的是,初始位置仅在没有分区检查点时使用;检查点将始终优先

从您所描述的场景来看,检查点似乎对您没有用处,并且阻碍了您首选的使用模式。如果没有其他缓解因素,我建议不要设置检查点,而是覆盖默认的起始位置,动态地重置到您感兴趣的时间


如果出于某种原因,您还需要检查点,那么您最好的选择是删除检查点数据,因为检查点基于偏移量,并且无法识别用于定位的排队时间。

可以在分区初始化时请求其初始位置,这将允许您指定排队时间作为起点。这说明了细节。需要注意的是,初始位置仅在没有分区检查点时使用;检查点将始终优先

从您所描述的场景来看,检查点似乎对您没有用处,并且阻碍了您首选的使用模式。如果没有其他缓解因素,我建议不要设置检查点,而是覆盖默认的起始位置,动态地重置到您感兴趣的时间

如果出于某种原因,您还需要检查点,那么您的最佳选择是删除检查点数据,因为检查点基于偏移量,无法识别排队时间进行定位