You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化.NET 6中Pusher Channels批量事件的消息发布性能?

优化Pusher批量消息发送性能的方案

针对你用.NET 6通过Pusher Channels给大量独立用户频道发消息的场景,以下是几个关键优化点,可大幅降低处理耗时:

1. 并行处理批量请求

当前代码是串行发送每个10事件的批次,10000个事件需要1000次串行HTTP请求,这是耗时的核心原因。可以用Task.WhenAll或Parallel.ForEachAsync(.NET 6+支持)并行处理多个批次的发送,利用多线程同时发起HTTP请求。

示例代码(Task.WhenAll):

var tasks = new List<Task<HttpStatusCode>>();
int chunkSize = 10;
int totalChunks = (int)Math.Ceiling((double)events.Count / chunkSize);

for (int i = 0; i < totalChunks; i++)
{
    var eventsChunk = events.Skip(i * chunkSize).Take(chunkSize).ToArray();
    // 将任务加入列表,不立即等待
    tasks.Add(pusher.TriggerAsync(eventsChunk));
}

// 等待所有并行任务完成
var results = await Task.WhenAll(tasks);
var statusCodes = results.ToList();

若需要控制并行度(避免触发Pusher速率限制),可使用ParallelOptions:

var statusCodesBag = new ConcurrentBag<HttpStatusCode>();
var options = new ParallelOptions { MaxDegreeOfParallelism = 20 }; // 调整合适的并行数

await Parallel.ForEachAsync(Enumerable.Range(0, totalChunks), options, async (i, ct) =>
{
    int startIndex = i * chunkSize;
    int endIndex = Math.Min(startIndex + chunkSize, events.Count);
    var eventsChunk = events.GetRange(startIndex, endIndex - startIndex).ToArray();
    
    var result = await pusher.TriggerAsync(eventsChunk, ct);
    statusCodesBag.Add(result.StatusCode);
});

2. 优化对象创建与字符串操作

  • 替换string.Format为字符串插值($""),性能更优且代码更简洁;
  • 用强类型类替代匿名对象存储Data,减少序列化时的反射开销;
  • 提前预计算频道名称等重复字符串,避免循环内重复生成。

优化后的事件创建代码:

// 定义强类型Data类
public class EventData
{
    public string Channel { get; set; }
    public string Event { get; set; }
    public string Message { get; set; }
}

var events = new List<Event>();
for (int i = 1; i <= count; i++)
{
    var channelName = $"batch-channel-{i}";
    events.Add(new Event
    {
        Channel = channelName,
        EventName = "batch-event",
        Data = new EventData
        {
            Channel = channelName,
            Event = "batch-event",
            Message = $"{i} - sample message"
        }
    });
}

3. 优化Pusher客户端的HttpClient配置

默认情况下,Pusher的.NET客户端可能为每个请求创建新的HttpClient,导致TCP连接反复创建销毁。建议复用HttpClient或用IHttpClientFactory管理客户端生命周期,提升HTTP请求效率。

依赖注入配置示例:

services.AddHttpClient<Pusher>(client =>
{
    client.BaseAddress = new Uri("https://api.pusherapp.com/");
    // 添加Pusher所需的默认请求头
})
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
    MaxConnectionsPerServer = 50 // 调整最大并发连接数
});

4. 减少内存与LINQ开销

避免循环中反复调用Skip+Take,改用List.GetRange直接操作底层数组,效率更高:

for (int i = 0; i < totalChunks; i++)
{
    int startIndex = i * chunkSize;
    int endIndex = Math.Min(startIndex + chunkSize, events.Count);
    var eventsChunk = events.GetRange(startIndex, endIndex - startIndex).ToArray();
    // 发送批次请求
}

额外建议

  • 检查Pusher API速率限制:确保并行请求数不超过平台限制,避免被限流;
  • 提前序列化Data:若序列化耗时较长,可在后台线程提前完成,避免阻塞发送流程;
  • 监控请求耗时:用日志记录每个批次的发送时间,排查是否存在网络或服务端异常。

内容的提问来源于stack exchange,提问作者Milind Mohapatra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 01:22:44