如何解压Gzip压缩的ReadOnlyMemory<byte>后调用JsonDocument.Parse
可插拔字节处理链路实现方案
不需要修改现有WebSocket库源码,直接在外层消息接收链路做一层拦截包装即可,具体实现分三步:
- 首先定义通用的二进制消息处理委托,默认实现为数据透传,保证未配置解压逻辑时和原有行为完全一致
// 字节处理委托签名,输入输出均为WebSocket传递的ReadOnlyMemory<byte>类型 public delegate ReadOnlyMemory<byte> BinaryMessageHandler(ReadOnlyMemory<byte> rawPayload); // 默认透传处理器,不对数据做任何修改 private static readonly BinaryMessageHandler DefaultPassthrough = raw => raw;
- 第二步将你已有的基于byte[]的Gzip解压方法,适配成符合委托签名的处理器,不需要修改原有解压方法的代码
public static BinaryMessageHandler BuildGzipDecompressHandler() { return raw => { // 直接复用现有已验证的Gzip解压逻辑 byte[] rawArray = raw.ToArray(); byte[] decompressedArray = YourExistingGzipDecompressMethod(rawArray); // 替换成你自己的解压方法 return new ReadOnlyMemory<byte>(decompressedArray); }; }
- 第三步在你现有的WebSocket消息接收逻辑中注入该处理器,消息到达后先经过处理器处理,再执行JSON解析
public class YourWebSocketConsumer { // 默认使用透传处理器,不改变原有行为 private BinaryMessageHandler _currentHandler = DefaultPassthrough; /// <summary> /// 可插拔配置入口,按需传入不同的字节处理逻辑 /// </summary> public void ReplaceMessageHandler(BinaryMessageHandler newHandler) { _currentHandler = newHandler ?? DefaultPassthrough; } // 你原有的WebSocket消息接收回调 private void OnMessageReceived(ReadOnlyMemory<byte> websocketBuffer) { // 先执行配置好的字节处理逻辑 ReadOnlyMemory<byte> readyToParseData = _currentHandler(websocketBuffer); // 处理完的数据直接交给JsonDocument解析即可 using var jsonDoc = JsonDocument.Parse(readyToParseData.Span); // 后续原有业务逻辑不需要做任何改动 } }
性能优化提示:如果对内存占用要求高,可以把Gzip解压逻辑改成直接接收
ReadOnlySpan<byte>输入,省去ToArray()产生的一次内存拷贝;如果现有解压逻辑已经稳定运行,优先做适配包装即可,没必要为了极致性能改动已经验证过的代码引入额外风险。
使用时只需要在需要开启Gzip解压的场景,调用ReplaceMessageHandler(BuildGzipDecompressHandler())即可,不需要解压的时候不配置或者传默认透传处理器就行,整个逻辑和WebSocket库完全解耦,不需要修改库的源码。
内容的提问来源于stack exchange,提问作者nop
相关产品推荐
相关产品推荐

