Skip to content

飞书WebSocket客户端服务

企业级飞书事件订阅WebSocket客户端,提供可靠的连接管理、自动重连和策略模式事件处理。

✨ 核心特性

  • 🔄 智能连接管理 - 自动重连、心跳检测、状态监控
  • 🫀 心跳消息处理 - 支持飞书 heartbeat 消息类型,实时连接状态监控
  • 🚀 高性能消息处理 - 异步处理、消息队列、并行执行
  • 🎯 策略模式事件处理 - 可扩展的事件处理器架构
  • 🛡️ 企业级稳定性 - 完善的错误处理、资源管理、日志记录
  • ⚙️ 灵活配置 - 丰富的配置选项、依赖注入支持
  • 📊 监控友好 - 详细的事件通知、性能指标、心跳统计

🚀 快速开始

1. 安装和注册服务

方式一:建造者模式(推荐)

csharp
// Program.cs
var builder = WebApplication.CreateBuilder(args);

// 使用建造者模式注册飞书WebSocket服务
builder.Services.AddFeishuWebSocketBuilder()
    .ConfigureFrom(builder.Configuration)           // 从配置文件读取
    .UseMultiHandler()                              // 启用多处理器模式
    .AddHandler<ReceiveMessageEventHandler>()        // 添加消息处理器
    .AddHandler<UserCreatedEventHandler>()           // 添加用户事件处理器
    .Build();                                       // 构建服务注册

var app = builder.Build();
app.Run();

方式二:简化注册

csharp
// 单处理器模式
builder.Services.AddFeishuWebSocketServiceWithSingleHandler<ReceiveMessageEventHandler>(
    options => {
        options.AutoReconnect = true;
        options.MaxReconnectAttempts = 5;
        options.HeartbeatIntervalMs = 30000;
    });

// 或多处理器模式
builder.Services.AddFeishuWebSocketServiceWithMultiHandler<ReceiveMessageEventHandler, UserCreatedEventHandler>(
    options => {
        options.AutoReconnect = true;
        options.EnableLogging = true;
    });

// 或从配置文件注册
builder.Services.AddFeishuWebSocketService(builder.Configuration);

2. 配置文件

json
{
  "Feishu": {
    "AppId": "your_app_id",
    "AppSecret": "your_app_secret",
    "WebSocket": {
      "AutoReconnect": true,
      "MaxReconnectAttempts": 5,
      "ReconnectDelayMs": 5000,
      "HeartbeatIntervalMs": 30000,
      "EnableLogging": true
    }
  }
}

3. 基本使用

csharp
public class MessageService
{
    private readonly IFeishuWebSocketManager _webSocketManager;

    public MessageService(IFeishuWebSocketManager webSocketManager)
    {
        _webSocketManager = webSocketManager;
        
        // 订阅连接事件
        _webSocketManager.Connected += OnConnected;
        _webSocketManager.Disconnected += OnDisconnected;
        _webSocketManager.Error += OnError;
        _webSocketManager.HeartbeatReceived += OnHeartbeatReceived;
    }

    private void OnConnected(object? sender, EventArgs e)
        => Console.WriteLine("🚀 WebSocket连接已建立");

    private void OnDisconnected(object? sender, WebSocketCloseEventArgs e)
        => Console.WriteLine($"🔌 连接已断开: {e.CloseStatusDescription}");

    private void OnError(object? sender, WebSocketErrorEventArgs e)
        => Console.WriteLine($"❌ 错误: {e.ErrorMessage}");

    private void OnHeartbeatReceived(object? sender, WebSocketHeartbeatEventArgs e)
        => Console.WriteLine($"💗 心跳消息: {e.Timestamp}, 间隔: {e.Interval}s, 状态: {e.Status}");
}

4. 心跳处理功能

心跳事件订阅

csharp
public class HeartbeatMonitorService : IHostedService
{
    private readonly IFeishuWebSocketManager _webSocketManager;
    private readonly List<DateTime> _heartbeatTimestamps = new();

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        // 订阅心跳事件
        _webSocketManager.HeartbeatReceived += OnHeartbeatReceived;
        
        _logger.LogInformation("心跳监控服务已启动");
    }

    private void OnHeartbeatReceived(object? sender, WebSocketHeartbeatEventArgs e)
    {
        _heartbeatTimestamps.Add(DateTime.UtcNow);
        
        _logger.LogInformation("💗 心跳消息 - 时间戳: {Timestamp}, 间隔: {Interval}s, 状态: {Status}",
            e.Timestamp, e.Interval, e.Status);
    }
}

心跳数据模型

csharp
// 心跳消息结构
public class HeartbeatMessage : FeishuWebSocketMessage
{
    public HeartbeatData? Data { get; set; }
}

public class HeartbeatData
{
    public long Timestamp { get; set; }           // 心跳时间戳
    public int? Interval { get; set; }           // 心跳间隔(秒)
    public string? Status { get; set; }           // 心跳状态
}

// 心跳事件参数
public class WebSocketHeartbeatEventArgs : EventArgs
{
    public HeartbeatMessage? HeartbeatMessage { get; set; }
    public DateTimeOffset Timestamp { get; set; }
    public int? Interval { get; set; }
    public string? Status { get; set; }
}

心跳统计和分析

csharp
public class HeartbeatStatistics
{
    public int TotalHeartbeats { get; set; }          // 总心跳次数
    public List<HeartbeatInfo> RecentHeartbeats { get; set; }  // 最近心跳记录
    public DateTime? LastHeartbeatTime { get; set; }   // 最后心跳时间
    public double? AverageInterval { get; set; }       // 平均心跳间隔
}

// 获取心跳统计
var statistics = heartbeatService.GetStatistics();
Console.WriteLine($"总心跳: {statistics.TotalHeartbeats}, 平均间隔: {statistics.AverageInterval:F2}s");

🎯 事件处理器(策略模式)

内置事件处理器

处理器事件类型说明
ReceiveMessageEventHandlerim.message.receive_v1接收消息事件
UserCreatedEventHandlercontact.user.created_v3用户创建事件
MessageReadEventHandlerim.message.message_read_v1消息已读事件
UserAddedToGroupEventHandlerim.chat.member.user_added_v1用户加入群聊
UserRemovedFromGroupEventHandlerim.chat.member.user_deleted_v1用户离开群聊
DefaultFeishuEventHandler-未知事件类型处理

创建自定义事件处理器

csharp
public class CustomEventHandler : IFeishuEventHandler
{
    private readonly ILogger<CustomEventHandler> _logger;

    public CustomEventHandler(ILogger<CustomEventHandler> logger)
        => _logger = logger ?? throw new ArgumentNullException(nameof(logger));

    public string SupportedEventType => "custom.event.example_v1";

    public async Task HandleAsync(EventData eventData, CancellationToken cancellationToken = default)
    {
        if (eventData == null) throw new ArgumentNullException(nameof(eventData));

        _logger.LogInformation("🎯 处理自定义事件: {EventType}", eventData.EventType);
        
        // 实现你的业务逻辑
        await ProcessBusinessLogicAsync(eventData);
    }

    private async Task ProcessBusinessLogicAsync(EventData eventData)
    {
        // 数据库操作、外部API调用等
        await Task.CompletedTask;
    }
}

注册自定义处理器

使用建造者模式注册(推荐)

csharp
// 注册多个自定义处理器
builder.Services.AddFeishuWebSocketBuilder()
    .ConfigureFrom(builder.Configuration)
    .UseMultiHandler()
    .AddHandler<CustomEventHandler>()                    // 类型注册
    .AddHandler<AnotherEventHandler>()                    // 第二个处理器
    .AddHandler(sp => new FactoryEventHandler(           // 工厂方法注册
        sp.GetService<ILogger<FactoryEventHandler>>(),
        sp.GetService<IConfiguration>()))
    .AddHandler(new InstanceEventHandler())               // 实例注册
    .Build();

依赖注入注册

csharp
// 注册处理器到 DI 容器
builder.Services.AddSingleton<CustomEventHandler>();
builder.Services.AddFeishuWebSocketService(builder.Configuration);

运行时动态注册

csharp
public class ServiceManager
{
    private readonly IFeishuEventHandlerFactory _factory;
    private readonly ILogger<ServiceManager> _logger;
    
    public ServiceManager(IFeishuEventHandlerFactory factory, ILogger<ServiceManager> logger)
    {
        _factory = factory;
        _logger = logger;
    }

    public void RegisterHandler()
    {
        var customHandler = new CustomEventHandler(_logger);
        _factory.RegisterHandler(customHandler);
        _logger.LogInformation("已注册自定义处理器: {HandlerType}", typeof(CustomEventHandler).Name);
    }
}

⚙️ 配置选项

WebSocket配置

选项类型默认值说明
AutoReconnectbooltrue自动重连
MaxReconnectAttemptsint5最大重连次数
ReconnectDelayMsint5000重连延迟(ms)
HeartbeatIntervalMsint30000心跳间隔(ms)
ConnectionTimeoutMsint10000连接超时(ms)
ReceiveBufferSizeint4096接收缓冲区大小
EnableLoggingbooltrue启用日志
EnableMessageQueuebooltrue启用消息队列
MessageQueueCapacityint1000消息队列容量
EnableMultiHandlerModeboolfalse启用多处理器模式
ParallelMultiHandlersbooltrue多处理器并行执行

代码配置

建造者模式配置(推荐)

csharp
builder.Services.AddFeishuWebSocketBuilder()
    .ConfigureOptions(options => {
        options.AppId = "your_app_id";
        options.AppSecret = "your_app_secret";
        options.AutoReconnect = true;
        options.MaxReconnectAttempts = 10;
        options.ReconnectDelayMs = 3000;
        options.HeartbeatIntervalMs = 25000;
    })
    .UseMultiHandler()
    .AddHandler<CustomHandler1>()
    .AddHandler<CustomHandler2>()
    .Build();

简化配置

csharp
// 单处理器模式
builder.Services.AddFeishuWebSocketServiceWithSingleHandler<CustomHandler>(
    options => {
        options.AppId = "your_app_id";
        options.AppSecret = "your_app_secret";
        options.AutoReconnect = true;
        options.MaxReconnectAttempts = 10;
        options.ReconnectDelayMs = 3000;
        options.HeartbeatIntervalMs = 25000;
    });

// 多处理器模式
builder.Services.AddFeishuWebSocketServiceWithMultiHandler<Handler1, Handler2>(
    options => {
        options.AppId = "your_app_id";
        options.AppSecret = "your_app_secret";
        options.AutoReconnect = true;
        options.EnableLogging = true;
    });

🎯 建造者模式高级用法

灵活的配置组合

csharp
// 场景1:多环境配置
var builder = services.AddFeishuWebSocketBuilder();

if (builder.Environment.IsDevelopment())
{
    builder.ConfigureOptions(options => {
        options.EnableLogging = true;
        options.HeartbeatIntervalMs = 15000;
    });
}
else if (builder.Environment.IsProduction())
{
    builder.ConfigureFrom(configuration, "Production:WebSocket");
}

builder.UseMultiHandler()
       .AddHandler<DevEventHandler>()
       .AddHandler<ProdEventHandler>()
       .Build();

条件性处理器注册

csharp
services.AddFeishuWebSocketBuilder()
    .ConfigureFrom(configuration)
    .UseMultiHandler()
    .AddHandler<BaseEventHandler>()
    .Apply(builder => {
        // 根据功能开关注册处理器
        if (configuration.GetValue<bool>("Features:EnableAudit"))
            builder.AddHandler<AuditEventHandler>();
        
        if (configuration.GetValue<bool>("Features:EnableAnalytics"))
            builder.AddHandler<AnalyticsEventHandler>();
    })
    .Build();

服务注册最佳实践

csharp
// 推荐:使用扩展方法封装复杂配置
public static class FeishuWebSocketExtensions
{
    public static IServiceCollection AddFeishuWebSocketWithDefaultHandlers(
        this IServiceCollection services, 
        IConfiguration configuration)
    {
        return services.AddFeishuWebSocketBuilder()
            .ConfigureFrom(configuration)
            .UseMultiHandler()
            .AddHandler<ReceiveMessageEventHandler>()
            .AddHandler<UserCreatedEventHandler>()
            .AddHandler<MessageReadEventHandler>()
            .Build();
    }
}

// 使用时更简洁
builder.Services.AddFeishuWebSocketWithDefaultHandlers(builder.Configuration);

🔧 高级功能

心跳监控服务

csharp
public class HeartbeatMonitorService : IHostedService
{
    private readonly IFeishuWebSocketManager _webSocketManager;
    private readonly List<DateTime> _heartbeatTimestamps = new();

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        // 订阅心跳事件
        _webSocketManager.HeartbeatReceived += OnHeartbeatReceived;
        
        // 启动定时检查
        _heartbeatCheckTimer = new Timer(CheckHeartbeatStatus, null, 
            TimeSpan.Zero, TimeSpan.FromSeconds(30));
    }

    private void OnHeartbeatReceived(object? sender, WebSocketHeartbeatEventArgs e)
    {
        _heartbeatTimestamps.Add(DateTime.UtcNow);
        
        // 分析心跳模式
        AnalyzeHeartbeatPattern();
        
        _logger.LogInformation("💗 收到心跳消息 - 时间戳: {Timestamp}, 间隔: {Interval}s, 状态: {Status}",
            e.Timestamp, e.Interval, e.Status);
    }

    private void AnalyzeHeartbeatPattern()
    {
        var recentTimestamps = _heartbeatTimestamps.TakeLast(10).ToList();
        var intervals = new List<double>();

        for (int i = 1; i < recentTimestamps.Count; i++)
        {
            var interval = (recentTimestamps[i] - recentTimestamps[i - 1]).TotalSeconds;
            intervals.Add(interval);
        }

        if (intervals.Any())
        {
            var averageInterval = intervals.Average();
            var variance = intervals.Select(x => Math.Pow(x - averageInterval, 2)).Average();
            var standardDeviation = Math.Sqrt(variance);

            // 如果标准差过大,可能表示心跳不稳定
            if (standardDeviation > 5.0)
            {
                _logger.LogWarning("检测到心跳间隔不稳定,可能存在连接问题");
            }
        }
    }

    public HeartbeatStatistics GetStatistics()
    {
        return new HeartbeatStatistics
        {
            TotalHeartbeats = _heartbeatTimestamps.Count,
            RecentHeartbeats = _heartbeatTimestamps.TakeLast(20)
                .Select((timestamp, index) => new HeartbeatInfo { Timestamp = timestamp })
                .ToList(),
            LastHeartbeatTime = _heartbeatTimestamps.LastOrDefault(),
            AverageInterval = CalculateAverageInterval(_heartbeatTimestamps.TakeLast(20).ToList())
        };
    }
}

事件处理器工厂

csharp
public class EventHandlerManager
{
    private readonly FeishuEventHandlerFactory _factory;

    public EventHandlerManager(FeishuEventHandlerFactory factory)
        => _factory = factory;

    // 获取处理器
    public IFeishuEventHandler GetHandler(string eventType)
        => _factory.GetHandler(eventType);

    // 注册处理器
    public void RegisterHandler(IFeishuEventHandler handler)
        => _factory.RegisterHandler(handler);

    // 检查注册状态
    public bool IsRegistered(string eventType)
        => _factory.IsHandlerRegistered(eventType);

    // 获取所有事件类型
    public IReadOnlyList<string> GetAllEventTypes()
        => _factory.GetRegisteredEventTypes();
}

手动连接控制

csharp
public class ConnectionController
{
    private readonly IFeishuWebSocketManager _manager;

    public ConnectionController(IFeishuWebSocketManager manager)
        => _manager = manager;

    // 启动连接
    public async Task StartAsync()
        => await _manager.StartAsync();

    // 发送消息
    public async Task SendMessageAsync(string message)
        => await _manager.SendMessageAsync(message);

    // 重新连接
    public async Task ReconnectAsync()
        => await _manager.ReconnectAsync();

    // 停止连接
    public async Task StopAsync()
        => await _manager.StopAsync();
}

分布式部署支持

csharp
public class DistributedEventProcessor
{
    private readonly IDistributedLockProvider _lockProvider;
    private readonly ILogger<DistributedEventProcessor> _logger;

    public async Task ProcessEventAsync(string eventId, EventData eventData)
    {
        var lockKey = $"feishu_event_{eventId}";
        
        await using (await _lockProvider.AcquireLockAsync(lockKey, TimeSpan.FromMinutes(1)))
        {
            // 获取锁成功,处理事件
            _logger.LogInformation("🔄 处理事件: {EventId}", eventId);
            await ProcessEventInternalAsync(eventData);
        }
        // 获取锁失败,说明其他实例正在处理
    }
}

📈 性能优化

消息处理优化

  • 异步处理 - 所有事件处理器使用异步方法
  • 并行执行 - 多个事件处理器可并行运行
  • 错误隔离 - 单个处理器异常不影响其他处理器
  • 批量处理 - 支持批量处理相似事件

连接管理优化

  • 智能心跳 - 根据网络环境自动调整心跳间隔
  • 连接池 - 高并发场景下支持连接池管理
  • 资源管理 - 自动释放连接资源,防止内存泄漏

监控和告警

  • 性能指标 - 消息处理延迟、队列大小等监控
  • 结构化日志 - 详细的日志记录和错误追踪
  • 健康检查 - 连接状态和健康状态监控

🐛 常见问题

连接问题

Q: 连接频繁断开?

  • 检查网络稳定性
  • 调整心跳间隔至30秒以内
  • 启用自动重连功能
  • 监控 heartbeat 消息的接收情况

Q: 认证失败?

  • 验证AppId和AppSecret是否正确
  • 检查应用权限配置
  • 确认网络访问权限

Q: 没有收到心跳消息?

  • 确认 WebSocket 连接已建立
  • 检查是否订阅了 HeartbeatReceived 事件
  • 验证飞书服务器是否支持 heartbeat 消息类型
  • 查看应用日志中的心跳相关错误

心跳问题

Q: 心跳间隔不稳定?

  • 检查网络延迟和稳定性
  • 使用心跳统计功能分析间隔模式
  • 考虑在网络波动时增加重试机制

Q: 如何使用心跳进行连接健康检查?

  • 监控 HeartbeatReceived 事件触发频率
  • 设置心跳超时检测(如2分钟无心跳视为异常)
  • 结合连接状态进行综合判断

性能问题

Q: 消息处理延迟?

  • 优化事件处理器逻辑,使用异步操作
  • 增加消息队列容量
  • 使用多个消费者处理事件
  • 监控心跳统计以评估连接质量

Q: 内存占用过高?

  • 及时处理积压的消息
  • 调整消息队列容量
  • 监控内存使用情况
  • 定期清理心跳统计数据

📋 支持的事件类型

WebSocket 消息类型

  • ping - 连接保活消息(自动响应 pong)
  • pong - 连接保活响应
  • heartbeat - 心跳消息(包含状态和间隔信息)
  • event - 业务事件消息
  • auth - 认证响应消息

消息事件

  • im.message.receive_v1 - 接收消息
  • im.message.message_read_v1 - 消息已读

群聊事件

  • im.chat.member.user_added_v1 - 用户加入群聊
  • im.chat.member.user_deleted_v1 - 用户离开群聊
  • im.chat.updated_v1 - 群聊信息更新

用户事件

  • contact.user.created_v3 - 用户创建
  • contact.user.updated_v3 - 用户更新
  • contact.user.deleted_v3 - 用户删除

部门事件

  • contact.department.created_v3 - 部门创建
  • contact.department.updated_v3 - 部门更新
  • contact.department.deleted_v3 - 部门删除

审批事件

  • approval.approval.approved_v1 - 审批通过
  • approval.approval.rejected_v1 - 审批拒绝

日程事件

  • calendar.event.updated_v4 - 日程事件

会议事件

  • meeting.meeting.started_v1 - 会议开始
  • meeting.meeting.ended_v1 - 会议结束

🔄 API 参考

IFeishuWebSocketManager

csharp
public interface IFeishuWebSocketManager
{
    // 属性
    IFeishuWebSocketClient Client { get; }
    bool IsConnected { get; }
    
    // 事件
    event EventHandler<EventArgs>? Connected;
    event EventHandler<WebSocketCloseEventArgs>? Disconnected;
    event EventHandler<WebSocketMessageEventArgs>? MessageReceived;
    event EventHandler<WebSocketErrorEventArgs>? Error;
    event EventHandler<WebSocketHeartbeatEventArgs>? HeartbeatReceived;  // 心跳事件
    
    // 方法
    Task StartAsync(CancellationToken cancellationToken = default);
    Task StopAsync(CancellationToken cancellationToken = default);
    Task SendMessageAsync(string message, CancellationToken cancellationToken = default);
    Task ReconnectAsync(CancellationToken cancellationToken = default);
}

IFeishuEventHandler

csharp
public interface IFeishuEventHandler
{
    string SupportedEventType { get; }
    Task HandleAsync(EventData eventData, CancellationToken cancellationToken = default);
}

📄 许可证

本项目遵循 MIT 许可证进行分发和使用。