闪电侠 Netty 小册里的骚操作
前言
即使这是一本小册,但基于“不提笔不读书”的理念,仍然有必要总结一下。此小册对于那些“硬杠 Netty 源码 却不曾在千万级生产环境上使用实操”的用户非常有用。当然,对那些没有 Netty 编程经验的人来说,更为有用。
放个小册地址:[Netty 入门与实战:仿写微信 IM 即时通讯系统
](https://juejin.im/book/5b4bc28bf265da0f60130116/section/5b4db06d5188251afc257383#heading-2)
再次强烈推荐,一碗黄焖鸡/半杯 Luckin coffee/一包炫赫门 的价钱,可以让你学会使用 Java 界的 epoll 进行多路复用网络编程,不能说是不划算的 :)
本文标题含有“骚操作”,为什么这么说呢?
作者是某团某评基础架构部技术专家,长期负责后台千万级别的推送系统,而这些推送系统自然是长连接实现的。可以想象,作者的这些实践经验不可谓不好用,纵然看过源码,提过 issue,本人也觉得这些操作非常好用,非常骚气。
开始
我们挑重点讲,虽然对于强迫症来讲,每一节都有笔记才是最吼的!
1 服务端启动流程
1. 通过给 bind 方法添加监听器,用以自动绑定递增端口。算骚操作吧?
2. attr 方法,为每条连接增加属性,能够实现全单例模式哟
3. childOption 方法,关于 TCP连接的优化,SO_KEEPALIVE 底层心跳,TCP_NODELAY 延迟发送,SO_BACKLOG 等待队列
2 客户端启动流程
1. 还是通过监听器实现重试,但是是 connect 返回的 future,且重实间隔时间左移 1 位增加(性能优化,不使用乘二 ,优秀)。
2. 重试不在主线程,而是使用 bootstrap.config().group().schedule 搞定时任务,和我想的不一样。优秀
3. 客户端需要 CONNECT_TIMEOUT_MILLIS 属性
3 客户端与服务端双向通信
1.客户端在 channelActive 立刻搞事情,嗯,rpc 通信通常也会做一些处理,例如打印客户端ip之类的。
4 客户端与服务端通信协议编解码(扩展较多)
emm,这个其实就是自定义应用层协议。
1. 4 字节魔数校验,例如 dubbo 就使用0xdabb进行校验,Java 字节码也使用 0xcafebabe 校验字节码。
2. 版本号肯定需要的
3. 序列化算法,肯定也需要的
4. 指令,肯定也是需要的,不过,也可以使用别的方式。
5. 后面的数据长度,也是需要的,方便拆包。
其实这里可以参照 RPC 协议来看,这里更像一个简化的 RPC 协议。
一般 RPC 框架首先获取协议类型,根据这个协议类型得到协议处理器,然后再处理(一个端口处理多个协议的场景)。
生产级别的 RPC 通常较为复杂,以 SOFABolt 为例,需要以下字段:
1. 协议版本
2. 请求类型,即指令(Request,Response, oneway)
3. 指令版本
4. RequestID 负责数据对应
5. 序列号器
6. 协议开关(例如 CRC 校验,安全校验)
7. 响应码,约定异常,简化异常
8. 类名长度,Java rpc 框架必备
9. 请求头长度(参照 http header)
10. 请求体长度(参照http body)
11. 类名
12. 业务请求头内容(一般是 Map,SOFABolt 支持自定义,SOFARPC 里面藏着是否泛化调用等信息)
13. 业务请求体内容(一般就是个Request对象或 Response对象,里面包含约定的属性,例如参数,返回值,超级多,SOFARPC 有个属性类 RemotingConstants,这里都有)
14. CRC 校验码(金融场景必备)
5 实现客户端与服务端收发消息
1. 使用 hannel.attr(Attributes.LOGIN).set(true) 绑定登录标识方便哟
6 构建客户端与服务端 pipeline
1. 常用的 ChannelInboundHandlerAdapter 和 ChannelOutboundHandlerAdapter 但是需要强转哦,麻烦,
建议使用 SimpleChannelInboundHandler (还帮你释放内存哟)。
2. 不使用 MessageToByteEncoder ,可以自己编解码哦,虽然麻烦点
7 拆包粘包理论与解决方案
1. 常用拆包:固定长度,行拆包(有bug,我写过文章分析),分隔符,基于长度
2. 最通用的就是基于长度,只要你的自定义协议中包含长度域字段,就可以使用
3. LengthFieldBasedFrameDecoder 代替自己继承 ByteToMessageDecoder 哟。
4. 对 LengthFieldBasedFrameDecoder 扩展一下,校验魔数关闭错误连接美滋滋。
8 channelHandler 的生命周期
1. 在 channelReadComplete 方法里执行 flush,批量刷新,性能提升美滋滋。
2. channelActive 和 channelInActive 增减连接,RPC 都这么干
9 使用 channelHandler 的热插拔实现客户端身份校验
1. ctx.pipeline().remove(this) 删除没有必要的 handler 美滋滋
2. handlerRemoved 回调美滋滋
10 客户端互聊原理与实现
1. Session 通过 channel.attr(Attributes.SESSION).set(session) 绑定连接美滋滋。
2. channel.attr(Attributes.SESSION).set(null) 删除 session 美滋滋
3. channel.attr(Attributes.SESSION).get() 美滋滋
11 群聊的发起与通知
1. ChannelGroup c = ChannelGroup channelGroup = new DefaultChannelGroup(ctx.executor()) 批量处理连接美滋滋
2. channelGroup.writeAndFlush 批量写连接美滋滋
高能预警!!!!
12 牛逼的性能优化
1. 共享 handler
2. 压缩 handler - 合并编解码器 —— MessageToMessageCodec
3. 虽然有状态的 handler 不能搞单例,但是你可以绑定到 channel 属性上,强行单例
4. 缩短事件传播路径—— 放 Map 里,在第一个 handler 里根据指令来找具体 handler。
5. 更改事件传播源—— 用 ctx.writeAndFlush() 不要用 ctx.channel().writeAndFlush()
6. 减少阻塞主线程的操作—— 使用业务线程池,RPC 优化重点
7. 计算耗时,使用回调 Future
13 心跳和空闲检测
1. 空闲检测 IdleStateHandler 用起来很爽, channelIdle 和 userEventTriggered 都可以处理
2. 定时心跳 ctx.executor().scheduleAtFixedRate 很优秀
3. 通常空闲检测时间要比发送心跳的时间的两倍要长一些(3倍),这也是为了排除偶发的公网抖动,防止误判。美滋滋
总结
小小短文,无法尽数 Netty 精华,但对于新手来说,已经足够使用了。而我这里仅仅是做简单的阅读总结,更多的内容,还需要读者自己去研究小册,研究源码,研究 Netty 在 RPC 里的运用,方能成为 Netty 多路复用网络编程高手。
关于 RPC 里使用 Netty 的最佳范例,推荐蚂蚁金服开源框架 SOFABolt,可以说是对 Netty 编程最佳实践的提炼,和此文相辅相成进行学习,可助汝纵横 Java 各种面试。
good luck!!!
闪电侠 Netty 小册里的骚操作的更多相关文章
- MySQL之B+树索引(转自掘金小册 MySQL是怎样运行的,版权归作者所有!)
每个索引都对应一棵B+树,B+树分为好多层,最下边一层是叶子节点,其余的是内节点.所有用户记录都存储在B+树的叶子节点,所有目录项记录都存储在内节点. InnoDB存储引擎会自动为主键(如果没有它会自 ...
- MySQL之 InnoDB记录结构(转自掘金小册 MySQL是怎样运行的,版权归作者所有!)
以下内容来自掘金小册 MySQL 是怎样运行的:从根儿上理解 MySQL 版权归原作者所有! 页是MySQL中磁盘和内存交互的基本单位,也是MySQL是管理存储空间的基本单位. 指定和修改行格式的语法 ...
- 一波骚操作,我把 SQL 执行效率提高了 10,000,000 倍!
作者:风过无痕-唐 http://www.cnblogs.com/tangyanbo/p/4462734.html 场景 我用的数据库是mysql5.6,下面简单的介绍下场景 课程表: create ...
- 你没玩过的全新版本!Win10这些骚操作你知多少
你没玩过的全新版本!Win10这些骚操作你知多少 [PConline技巧]不知不觉,Win10与我们相伴已经整整四个年头了,从最开始的组团抗拒到现在的默默接受,个中滋味相信谁心里都有个数.近日微软开始 ...
- 开源项目在闲鱼、b 站上被倒卖?这是什么骚操作?
起因 - 又是一封邮件 2020 年 3 月 2 日,收到了一封邮件,对,这次故事的起因又是一封邮件,和上次写个bug被国家信息安全漏洞共享平台抓到了一样. 这是一条评论通知邮件,一开始我以为只是正常 ...
- Redis 数据结构之字符串的那些骚操作
Redis 字符串底层用的是 sds 结构,该结构同 c 语言的字符串相比,其优点是可以节省内存分配的次数,还可以... 这样写是不是读起来很无聊?这些都是别人咀嚼过后,经过一轮两轮三轮的再次咀嚼,吐 ...
- newbee-mall开源项目被慕课网拿去做课程,然后我毫不知情,这又是什么骚操作?
万万没想到,这种事情会发生在我身上. 之前写过<开源囧事>系列而且已经写了四篇,四次开源囧事如下: <开源囧事(一)捅娄子了,写个bug被国家信息安全漏洞共享平台抓到了?> & ...
- 如何在命令长度受限的情况下成功get到webshell(函数参数受限突破、mysql的骚操作)
0x01 问题提出 还记得上篇文章记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门),我们讲到了一些PHP的一些如何巧妙地绕过数字和字母受限的技巧,今天我要给大家分享的是如 ...
- UOJ 117 欧拉回路(套圈法+欧拉回路路径输出+骚操作)
题目链接:http://uoj.ac/problem/117 题目大意: 解题思路:先判断度数: 若G为有向图,欧拉回路的点的出度等于入度. 若G为无向图,欧拉回路的点的度数位偶数. 然后判断连通性, ...
随机推荐
- 可遇不可求的Question之MySql4.0前版本不支持union与批量SQL提交
批量SQL提交 参考 21.2.6. Connector/NET Connection String Options Reference . Allow Batch true When true, m ...
- ASCII、Unicode、UTF-8以及Python3编码问题
编码问题,其实的确是个很烦人的问题,一开始觉得不需要看,到后来出现问题,真的是抓狂, 而像我们这些刚刚涉及到这些问题的小白来说,更是无从下手,所以查阅资料,总结理解下各个概念以及Python3的编码问 ...
- Base64格式上传文件至阿里云(java)
Controller @PostMapping("/save") public R save(@RequestBody ShareEntity share){ OSSClient ...
- (三)Javascript面向对象编程:非构造函数的继承
Javascript面向对象编程:非构造函数的继承 这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现"继承". 今天是最后一个部分,介绍不使 ...
- kaldi运行thchs30例子
首先,thchs30有两种数据库,kaldi运行的数据库最好是 thchs30-openslr. 修改run.sh里面的语音库路径 thchs30=... 修改nj线程数 等于CPU的核心数 修改c ...
- 【CSS/JS】如何实现单行/多行文本溢出的省略(...)--老司机绕过坑道的正确姿势
写前端UI的朋友们也许都遇到过这样的问题:我们需要实现这样一个需求,在一个父级元素中隐藏一个可能过长的文本: 这个文本可能是单行的: 也可能是多行的: 下面我就给大家展示如何简单或优雅地实 ...
- Java的简单类型不能够精确的对浮点数进行运算
由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精确的浮点数运算,包括加减乘除和四舍五入. import java.math.BigDecimal; /** * 由于Java的简单类 ...
- Hadoop 单表关联
前面的实例都是在数据上进行一些简单的处理,为进一步的操作打基础.单表关联这个实例要求从给出的数据中寻找到所关心的数据,它是对原始数据所包含信息的挖掘.下面进入这个实例. 1.实例描述 实例中给出chi ...
- Android Tools 开发工具库开源项目总结
在Android开发中,我们不免会遇到使用一些工具库来简化我们的工具代码的编写,以下是本人之前star的开源项目,供大家参考: 一.android_testsuite 项目地址:https://git ...
- ScrollView嵌套子View的getDrawingCache为空的解决方法
ScrollView嵌套子View的getDrawingCache为空的解决方法 问题 将组件的显示布局改为可以滚动的,然后用ScrollView作为了View的父类,发现View的getDrawin ...