设计网站首页1营销网站建设大概费用

张小明 2026/1/1 22:25:17
设计网站首页1,营销网站建设大概费用,企业还有人做网站么,超市小程序怎么做Protobuf vs JSON#xff1a;为什么 IM 系统选择二进制协议#xff1f; 在 IM 系统中#xff0c;消息序列化协议的选择直接影响性能和用户体验#xff0c;本文对比 Protobuf 与 JSON#xff0c;并说明为什么选择 Protobuf。 一、为什么需要关注序列化协议#xff1f; 在 …Protobuf vs JSON为什么 IM 系统选择二进制协议在 IM 系统中消息序列化协议的选择直接影响性能和用户体验本文对比 Protobuf 与 JSON并说明为什么选择 Protobuf。一、为什么需要关注序列化协议在 IM 系统中每条消息都需要序列化后通过网络传输。假设系统每秒处理 1 万条消息如果每条消息序列化耗时 1ms每秒会消耗 10 秒 CPU 时间如果每条消息体积 1KB每秒需要传输 10MB 数据在高并发场景下序列化协议的选择会显著影响系统性能。二、Protobuf vs JSON性能对比1.体积对比JSON 格式示例{msgId:msg_1234567890,roomId:room_abc123,userId:user_xyz789,msgType:0,msg:这是一条测试消息,ext:}体积约 150 字节包含字段名、引号、逗号等Protobuf 格式示例message SendMsgCmd { string msgId 1; string roomId 2; int32 msgType 3; string msg 4; string ext 5; }体积约 50-80 字节二进制格式无字段名对比结果JSON150 字节Protobuf50-80 字节体积减少30-50%2.序列化/反序列化性能对比测试代码// JSON 序列化StringjsonJSONObject.toJSONString(messageDto);byte[]jsonBytesjson.getBytes(StandardCharsets.UTF_8);// Protobuf 序列化byte[]protoBytessendMsgCmd.toByteArray();性能测试结果基于 AQChat 项目的实际测试操作JSONProtobuf性能提升序列化0.5ms0.1ms5倍反序列化0.6ms0.15ms4倍消息体积150字节60字节60% 减少实际效果响应时间从 50ms 降到 10ms序列化性能提升重要因素之一带宽节省10 万并发用户每秒节省约 9MB 贷款CPU 使用序列化 CPU 时间减少 80%三、Protubuf 向后兼容性1.字段扩展场景需要在消息中新增字段但不影响旧版本客户端。JSON 方案// 旧版本{msgId:123,msg:hello}// 新版本新增 userId 字段{msgId:123,msg:hello,userId:user_123}问题旧版本客户端解析新版本消息时可能因为未知字段出错。Protobuf 方案// 旧版本 message SendMsgCmd { string msgId 1; string msg 2; } // 新版本新增 userId 字段编号 3 message SendMsgCmd { string msgId 1; string msg 2; string userId 3; // 新增字段编号不能重复 }优势旧版本客户端可以正常解析忽略未知字段新版本客户端可以读取新字段字段编号一旦使用不能修改保证兼容性3.实际案例在 AQChat 项目中消息协议经历了多次扩展// 最初版本 message SendMsgCmd { string msgId 1; string roomId 2; string msg 3; } // 扩展版本新增 msgType 和 ext 字段 message SendMsgCmd { string msgId 1; string roomId 2; MsgType msgType 3; // 新增消息类型 string msg 4; string ext 5; // 新增扩展字段 }旧版本客户端仍可以正常解析只是无法读取新字段保证了向后兼容。四、消息识别器的设计思路1.问题如何根据指令编号设计消息类型在自定义协议中消息格式是消息长度4 字节 消息指令2 字节 Protobuf消息体解码时如何根据指令编号如 10获取对应的 Protobuf Builder2.解决方案反射机制自动映射核心思路通过反射扫描 Protobuf 协议中的所有消息类型通过类名匹配消息指令枚举自动建立双向映射关系代码实现ComponentpublicclassMessageRecognizerimplementsInitializingBean{// 指令编号 - 消息实例的映射用于解码privatefinalMapInteger,GeneratedMessageV3msgCommandAndMsgBodyMapnewHashMap();// 消息类型 - 指令编号的映射用于编码privatefinalMapClass?,IntegermsgClazzAndMsgCommandMapnewHashMap();publicvoidinit(){// 1. 获取 Protobuf 协议文件中的所有内部类Class?[]innerClazzArrayAQChatMsgProtocol.class.getDeclaredClasses();for(Class?innerClazz:innerClazzArray){// 2. 过滤出消息类型继承自 GeneratedMessageV3if(!GeneratedMessageV3.class.isAssignableFrom(innerClazz)){continue;}// 3. 获取类名并转换为小写去掉下划线StringclazzNameinnerClazz.getSimpleName().toLowerCase();// 例如UserLoginCmd - userlogincmd// 4. 遍历消息指令枚举匹配类名for(AQChatMsgProtocol.MsgCommandmsgCommand:AQChatMsgProtocol.MsgCommand.values()){StringstrMsgCodemsgCommand.name().replaceAll(_,).toLowerCase();// 例如USER_LOGIN_CMD - userlogincmd// 5. 类名匹配指令名if(strMsgCode.equals(clazzName)){try{// 6. 通过反射调用 getDefaultInstance() 获取默认实例ObjectreturnObjinnerClazz.getDeclaredMethod(getDefaultInstance).invoke(innerClazz);// 7. 建立双向映射msgCommandAndMsgBodyMap.put(msgCommand.getNumber(),(GeneratedMessageV3)returnObj);msgClazzAndMsgCommandMap.put(innerClazz,msgCommand.getNumber());LOGGER.info(消息识别器初始化: {} {},innerClazz.getName(),msgCommand.getNumber());}catch(Exceptionex){LOGGER.error(ex.getMessage(),ex);}}}}}// 解码时根据指令编号获取 BuilderpublicMessage.BuildergetMsgBuilderByMsgCommand(intmsgCommand){GeneratedMessageV3msgmsgCommandAndMsgBodyMap.get(msgCommand);if(msgnull){returnnull;}returnmsg.newBuilderForType();}// 编码时根据消息类型获取指令编号publicintgetMsgCommandByMsgClazz(Class?msgClazz){IntegercommandmsgClazzAndMsgCommandMap.get(msgClazz);returncommandnull?-1:command;}}3.命名规则为了保证自动映射需要遵循命名规则消息类型命名请求消息XxxCmd如UserLoginCmd响应消息XxxAck如UserLoginAck通知消息XxxNotify如JoinRoomNotify消息指令枚举请求指令XXX_CMD如USER_LOGIN_CMD响应指令XXX_ACK如USER_LOGIN_ACK通知指令XXX_NOTIFY如JOIN_ROOM_NOTIFY匹配规则去掉下划线和大小写进行匹配UserLoginCmd ↔USER_LOGIN_CMDJoinRoomNotify ↔JOIN_ROOM_NOTIFY4.优势1.自动映射新增消息类型时只需要在.protobuf文件中定义无需手动维护映射关系2.类型安全编译时检查避免运行时错误3.易于维护映射关系自动生成减少人工错误如何从 JSON 迁移到 Protobuf1.迁移步骤第一步定义 Protobuf 协议文件// AQChatMsgProtocol.proto syntaxproto3; package chat_msg; option java_package com.howcode.aqchat.message; enum MsgCommand{ USER_LOGIN_CMD 0; USER_LOGIN_ACK 1; SEND_MSG_CMD 10; SEND_MSG_ACK 11; // ... 更多指令 } message UserLoginCmd{ string userName 1; string userAvatar 2; } message SendMsgCmd{ string msgId 1; string roomId 2; int32 msgType 3; string msg 4; string ext 5; }第二步编译生成 Java 类# 使用 protoc 编译器 protoc --java_outsrc/main/java AQChatMsgProtocol.proto第三步实现编解码器// 编码器publicclassMessageEncoderextendsMessageToMessageEncoderGeneratedMessageV3{Overrideprotectedvoidencode(ChannelHandlerContextctx,GeneratedMessageV3msg,ListObjectlist){// 1. 获取消息指令编号intmsgCommandrecognizer.getMsgCommandByMsgClazz(msg.getClass());// 2. 序列化为字节数组byte[]msgBodymsg.toByteArray();// 3. 写入协议头部ByteBufbyteBufctx.alloc().buffer();byteBuf.writeInt(msgBody.length);// 消息长度byteBuf.writeShort((short)msgCommand);// 消息指令byteBuf.writeBytes(msgBody);// 消息体list.add(newBinaryWebSocketFrame(byteBuf));}}// 解码器publicclassMessageDecoderextendsMessageToMessageDecoderBinaryWebSocketFrame{Overrideprotectedvoiddecode(ChannelHandlerContextctx,BinaryWebSocketFramemsg,ListObjectlist){ByteBufbyteBufmsg.content();// 1. 读取消息长度和指令intmsgLengthbyteBuf.readInt();shortcommandbyteBuf.readShort();// 2. 根据指令获取对应的 BuilderMessage.Builderbuilderrecognizer.getMsgBuilderByMsgCommand(command);// 3. 读取消息体并反序列化byte[]msgBodynewbyte[msgLength];byteBuf.readBytes(msgBody);builder.mergeFrom(msgBody);list.add(builder.build());}}第四步修改业务代码// 原来的 JSON 方式StringjsonJSONObject.toJSONString(messageDto);ctx.writeAndFlush(json);// 改为 Protobuf 方式AQChatMsgProtocol.SendMsgCmdcmdAQChatMsgProtocol.SendMsgCmd.newBuilder().setMsgId(messageDto.getMessageId()).setRoomId(messageDto.getRoomId()).setMsgType(messageDto.getMessageType()).setMsg(messageDto.getMessageContent()).build();ctx.writeAndFlush(cmd);2.迁移注意事项1.字段类型映射JSON 类型Protobuf 类型说明stringstring字符串numberint32/int64整数booleanbool布尔值arrayrepeated数组objectmessage对象2.默认值处理Protobuf 的默认值string空字符串int32/int640boolfalserepeated空列表JSON 中可能没有这些默认字段需要特殊处理3.版本兼容迁移时建议先支持双协议JSON 和 Protobuf逐步迁移客户端到 Protobuf最后完全切换到 Protobuf六、Protobuf 的其他优势1.类型安全JSON 的问题{msgType:0,// 字符串类型容易出错roomId:12345// 数字类型应该是字符串}Protobuf 的优势message SendMsgCmd { int32 msgType 3; // 编译时检查类型 string roomId 2; // 类型明确 }编译时检查类型避免运行时错误2.代码生成Protobuf 自动生成 Java 类包含Builder 模式链式调用代码简洁序列化/反序列化方法toByteArray、mergeFrom字段访问器getMsgId()、setMsgId()3.跨语言支持Protobuf 支持多种语言Java、C、Python、JavaScript 等同一份.proto文件可以生成不同语言的代码便于多语言系统集成七、Protobuf 的局限性1.可读性差JSON人类可读便于调试Protobuf二进制格式不可读解决方法开发时使用 JSON生产环境使用 Protobuf。2.需要编译JSON无需编译直接使用Protobuf需要编译.proto文件生成代码解决方法使用 Maven/Gradle 插件自动编译。3.学习成本JSON简单直接Protobuf需要学习.proto语法解决方案.proto语法简单学习成本低。八、实际应用效果在 AQChat 项目中使用 Protobuf 后的效果1. 性能提升响应时间从 50ms 降到 10ms序列化性能提升是重要因素带宽节省消息体积减少 30-50%节省带宽CPU 使用序列化 CPU 时间减少 80%2. 代码质量类型安全编译时检查减少运行时错误代码生成自动生成代码减少手写代码易于维护协议定义集中便于管理3. 扩展性向后兼容支持字段扩展不影响旧版本跨语言支持多语言便于系统集成九、总结Protobuf 相比 JSON 的优势1.性能体积小 30-50%序列化速度快 3-5 倍2.类型安全编译时检查避免运行时错误3.向后兼容支持字段扩展不影响旧版本4.代码生成自动生成代码减少手写代码在 IM 系统这种高并发、低延迟的场景下Protobuf 是更好的选择。虽然 JSON 更易读、更简单但在性能要求高的场景下Protobuf 的优势更明显。选择建议高并发、低延迟场景选择 Protobuf简单场景、可读性要求高选择 JSON需要跨语言集成选择 Protobuf在 AQChat 项目中使用 Protobuf 后系统性能显著提升证明了二进制协议在高并发场景下的优势。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

食品经营许可网站增项怎么做钓鱼网站怎么制作视频

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个数据模型快速验证工具,使用MySQL WITH AS实现:1) 动态构建虚拟数据模型;2) 模拟多表关联关系;3) 实时查询验证;4…

张小明 2025/12/29 9:27:12 网站建设

做网页兼职网站怎么做app界面设计

无需设计基础!Excalidraw让你轻松画出专业图表 在一次远程技术评审会上,团队正在讨论新订单系统的架构。以往这种会议总是陷入“你说我听”的困境:有人描述着“API网关后面接用户服务,然后调用订单模块”,另一个人却理…

张小明 2025/12/31 2:47:57 网站建设

网站建设与设计开题报告做暧暧网站免费

TrollInstallerX下载拦截的全面应对指南 【免费下载链接】TrollInstallerX A TrollStore installer for iOS 14.0 - 16.6.1 项目地址: https://gitcode.com/gh_mirrors/tr/TrollInstallerX 亲爱的朋友们,最近是不是在为TrollInstallerX下载被拦截而烦恼呢&am…

张小明 2025/12/31 4:28:01 网站建设

网站制作公司哪里好wordpress hook 数据库

Langchain-Chatchat在心理咨询中的应用边界探讨:伦理与风险控制 在心理健康服务需求持续增长的今天,专业咨询师资源稀缺、服务成本高昂、隐私顾虑重重等问题日益凸显。越来越多机构开始探索人工智能技术在心理支持领域的可行性。其中,一种基…

张小明 2025/12/31 4:29:13 网站建设

金华建设监理协会网站成都公园城市建设局网站

Langflow插件生态完全指南:第三方组件深度解析 【免费下载链接】langflow ⛓️ Langflow 是 LangChain 的用户界面,使用 react-flow 设计,旨在提供一种轻松实验和原型设计流程的方式。 项目地址: https://gitcode.com/GitHub_Trending/la/l…

张小明 2025/12/31 7:05:36 网站建设

网站分析工具有哪些dw制作模板

音频剪辑新纪元:你是否曾为在海量音频文件中寻找特定内容而烦恼?Audiogrep作为一款革命性的音频超级剪辑工具,彻底改变了传统音频处理方式。通过智能语音识别技术,它能精准定位并提取你需要的任何音频片段,让声音搜索和…

张小明 2025/12/30 22:29:36 网站建设