Skip to content

chore: 移除应用层心跳,升级为协议层保活与死链检测#1233

Merged
joesdu merged 7 commits into
mainfrom
dev
Jun 30, 2026
Merged

chore: 移除应用层心跳,升级为协议层保活与死链检测#1233
joesdu merged 7 commits into
mainfrom
dev

Conversation

@joesdu

@joesdu joesdu commented Jun 30, 2026

Copy link
Copy Markdown
Owner

📝 描述 (Description)

  • 客户端/服务端全面移除 Heartbeat* 相关选项与实现,统一采用 .NET 8+ KeepAliveInterval/KeepAliveTimeout 进行协议层 PING/PONG 保活与死链检测
  • 新增接收分发队列(ReceiveDispatchQueueCapacity),接收循环与用户回调彻底解耦,慢处理器不再阻塞接收与保活检测,队列满时自动背压
  • 服务端支持 MaxMessageSize,超限主动断连,防御内存耗尽
  • 优化 SendTextAsync 内存分配,关闭连接增加超时保护,所有 API 保持线程安全
  • 客户端/服务端 README、XML 注释、参数校验等文档全面更新,去除应用层心跳说明,推荐协议层保活配置
  • 单元测试同步调整,移除 HeartbeatResponseMessage 配置

🔗 相关问题 (Related Issues)

  • Closes #
  • Fixes #

🏷️ 变更类型 (Type of Change)

  • 🐛 错误修复 (Bug fix) (non-breaking change which fixes an issue)
  • ✨ 新功能 (New feature) (non-breaking change which adds functionality)
  • 💥 破坏性变更 (Breaking change) (fix or feature that would cause existing functionality to not work as expected)
  • 📚 文档更新 (Documentation update)
  • 🔧 重构 (Refactor) (no functional changes)
  • 🧪 测试 (Tests) (adding or updating tests)
  • 🛠️ 构建/CI 变更 (Build/CI changes)
  • 🎨 样式变更 (Style changes) (formatting, etc.)
  • 🚀 性能改进 (Performance improvements)
  • 🔒 安全改进 (Security improvements)

✅ 检查清单 (Checklist)

  • 我的代码遵循项目的编码标准 (My code follows the project's coding standards)
  • 我已经对自己的代码进行了自我审查 (I have performed a self-review of my own code)
  • 我已经在难以理解的区域注释了我的代码 (I have commented my code, particularly in hard-to-understand areas)
  • 我已经对文档进行了相应的更改 (I have made corresponding changes to the documentation)
  • 我的更改不会产生新的警告或错误 (My changes generate no new warnings or errors)
  • 我已经添加了证明我的修复有效或我的功能工作的测试 (I have added tests that prove my fix is effective or that my
    feature works)
  • 新增和现有的单元测试在本地通过我的更改 (New and existing unit tests pass locally with my changes)
  • 任何依赖变更都已合并并发布到下游模块 (Any dependent changes have been merged and published in downstream modules)

🧪 测试 (Testing)

  • 单元测试 (Unit tests)
  • 集成测试 (Integration tests)
  • 手动测试 (Manual testing)
  • 其他 (请指定) (Other (please specify)):

📸 截图 (如果适用) (Screenshots (if applicable))

🔍 附加说明 (Additional Notes)

- 客户端/服务端全面移除 Heartbeat* 相关选项与实现,统一采用 .NET 8+ KeepAliveInterval/KeepAliveTimeout 进行协议层 PING/PONG 保活与死链检测
- 新增接收分发队列(ReceiveDispatchQueueCapacity),接收循环与用户回调彻底解耦,慢处理器不再阻塞接收与保活检测,队列满时自动背压
- 服务端支持 MaxMessageSize,超限主动断连,防御内存耗尽
- 优化 SendTextAsync 内存分配,关闭连接增加超时保护,所有 API 保持线程安全
- 客户端/服务端 README、XML 注释、参数校验等文档全面更新,去除应用层心跳说明,推荐协议层保活配置
- 单元测试同步调整,移除 HeartbeatResponseMessage 配置
Copilot AI review requested due to automatic review settings June 30, 2026 08:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

EN: Summary

This PR refactors EasilyNET’s WebSocket client/server to fully remove application-level heartbeat messages and rely on .NET 8+ protocol-level keep-alive (PING/PONG) for liveness, while also adding receive/dispatch decoupling and max inbound message size enforcement to improve robustness and prevent memory exhaustion.

Changes:

  • Remove Heartbeat* options/logic and switch to KeepAliveInterval + KeepAliveTimeout (protocol-level) on both client and server.
  • Introduce a bounded receive-dispatch queue (ReceiveDispatchQueueCapacity) to decouple receive loops from user callbacks with backpressure.
  • Add/strengthen max message size handling (server closes on oversize) and update docs/tests accordingly.

EN: Key issues

  • The sample TestMode flag is effectively forced to true and will run the background test service unconditionally.
  • ReceiveDispatchQueueCapacity is used to construct a bounded channel but lacks an explicit validation path on the server side, which can lead to confusing runtime exceptions.
  • WebSocketClientOptions XML docs describe keep-alive behavior as sending “PONG” when interval is set alone; this is misleading and should be corrected.

EN: Suggested changes

  • Restore TestMode to default-off (or gate it via configuration / compilation symbol).
  • Add explicit validation for ReceiveDispatchQueueCapacity near channel creation with a clear exception.
  • Correct XML docs to describe periodic PING frames when only KeepAliveInterval is set.

中文:总结

该 PR 对 EasilyNET 的 WebSocket 客户端/服务端进行了统一升级:彻底移除应用层 Heartbeat(业务 ping/pong 消息),改为使用 .NET 8+ 提供的协议层 KeepAlive(PING/PONG)实现保活与死链检测;同时通过接收-分发队列解耦,避免慢处理器阻塞接收循环,并加入/完善 MaxMessageSize 以防止内存耗尽攻击;文档与测试也同步更新。

变更点:

  • 移除 Heartbeat* 相关配置与实现,统一使用 KeepAliveInterval + KeepAliveTimeout
  • 新增 ReceiveDispatchQueueCapacity,接收循环与用户回调解耦,队列满时背压。
  • 服务端超限主动断连(MessageTooBig),并同步更新 README/XML 注释/单测。

中文:主要问题

  • sample 里的 TestMode => !false 等价于永远开启测试模式,会导致后台测试服务在任何环境都执行。
  • 服务端侧 ReceiveDispatchQueueCapacity 缺少显式校验,配置为 0/负数会在运行时抛出不直观异常。
  • WebSocketClientOptions 注释对 KeepAliveInterval 单独配置时的行为描述为 “PONG”,易误导使用者。

中文:修改建议

  • 将 sample 的测试模式恢复为默认关闭,或改为配置开关/编译条件控制。
  • 在服务端 WebSocketSession 构造处对 ReceiveDispatchQueueCapacity 做明确校验并抛出清晰异常信息。
  • 修正注释为:仅设置 KeepAliveInterval 时运行时周期性发送 PING,但不会因超时中止连接。

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
test/EasilyNET.Test.Unit/WebSocket/ManagedWebSocketClientTest.cs Update tests to remove HeartbeatResponseMessage usage.
test/EasilyNET.Test.Unit/WebSocket/ManagedWebSocketClientMaxMessageSizeTest.cs Adjust max-message-size tests after heartbeat removal.
src/EasilyNET.WebCore/WebSocket/WebSocketSessionOptions.cs Replace heartbeat options with MaxMessageSize, receive-dispatch queue, and keep-alive options.
src/EasilyNET.WebCore/WebSocket/WebSocketSession.cs Add receive/dispatch decoupling, max-size checks, close timeout handling, and send allocation tweaks.
src/EasilyNET.WebCore/WebSocket/README.md Rewrite docs to reflect protocol-level keep-alive and new session semantics.
src/EasilyNET.WebCore/Middleware/WebSocketMiddleware.cs Pass KeepAliveInterval/Timeout via WebSocketAcceptContext.
src/EasilyNET.Core/WebSocket/WebSocketClientOptions.cs Remove heartbeat options; add keep-alive timeout + receive-dispatch queue capacity; update validation/docs.
src/EasilyNET.Core/WebSocket/README.md Update client documentation to protocol-level keep-alive and new dispatch semantics.
src/EasilyNET.Core/WebSocket/ManagedWebSocketClient.cs Add persistent dispatch loop and remove heartbeat filtering/loop; improve send and state/close semantics.
sample/WebApi.Test.Unit/BackgroundServices/WebSocketClientTestService.cs Update sample client to use protocol-level keep-alive; (currently forces test mode on).

Comment thread src/EasilyNET.WebCore/WebSocket/WebSocketSession.cs
Comment thread src/EasilyNET.WebCore/WebSocket/WebSocketSession.cs
Comment thread src/EasilyNET.Core/WebSocket/WebSocketClientOptions.cs
Comment thread src/EasilyNET.Core/WebSocket/WebSocketClientOptions.cs
Comment thread sample/WebApi.Test.Unit/BackgroundServices/WebSocketClientTestService.cs Outdated
重构客户端测试服务,覆盖连接、状态机、回显、高并发、二进制、大消息、断开重连等多场景自动化断言,统一测试流程与统计输出。增强事件处理与日志,支持多轮连接/断开循环。服务端 ChatHandler 增加连接统计、消息计数、异常日志,优化日志输出与线程安全。整体提升测试覆盖率、可维护性和可观测性,为后续扩展打下基础。
@joesdu joesdu requested a review from Copilot June 30, 2026 09:08
@joesdu joesdu added the .NET Pull requests that update .net code label Jun 30, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Comment thread src/EasilyNET.WebCore/WebSocket/WebSocketSession.cs
Comment thread src/EasilyNET.WebCore/WebSocket/WebSocketSession.cs Outdated
Comment thread src/EasilyNET.Core/WebSocket/ManagedWebSocketClient.cs
Comment thread sample/WebApi.Test.Unit/BackgroundServices/WebSocketClientTestService.cs Outdated
Comment thread src/EasilyNET.WebCore/Middleware/WebSocketMiddleware.cs
joesdu and others added 5 commits June 30, 2026 17:14
将 TestMode 静态属性由返回 true 改为 false,切换为非测试模式运行。此更改可能影响测试逻辑分支,请关注相关用例行为变化。
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Joe Du <13188169+joesdu@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Joe Du <13188169+joesdu@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Joe Du <13188169+joesdu@users.noreply.github.com>
---
- 接收队列由 WebSocketMessageReceivedEventArgs 升级为携带 session 的 ReceivedEnvelope,提升消息归属判定能力
- 分发循环增加 session 校验,确保仅投递当前连接消息,避免断开/重连后旧消息误投递
- DrainReceiveChannel 方法同步适配,保证缓冲区安全释放
- 增强连接生命周期的消息隔离性与终态语义一致性
@joesdu joesdu merged commit 82fae6a into main Jun 30, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

.NET Pull requests that update .net code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants