1. handle创建在外部,所有的请求使用一个对象。
需要在该handle对象上部添加一个@ChannelHandler.Sharable
,让Netty知道这是一个共享对象。
但要注意在netty中handle复用的话,那么里面不能有共享的数据
,会产生线程安全问题。
2. 在网络速度有余力的情况下将Netty发送缓冲区和接收缓冲区调大。
ServerBootStrap b = new ServerBootstrap();
b.childOption(ChannelOption.SO_RCVBUF,32 * 1024);
b.childOption(ChannelOption.SO_SNDBUF,32 * 1024);
3. 对于耗时的任务尽量做成多线程
耗时操作交给线程池去处理,防止数据处理的handler阻塞read io 处理数据的EventLoopGroup。
- 自定义线程池
- 添加handler,定义处理handler的线程池,把该handler专门创建一个EventLoopGroup
//业务线程池 处理数据的线程池 并将其更换默认的名称有利于后续的错误排查
EventLoopGroup bizGroup = new NioEventLoopGroup(200,new DefaultThreadFactory("biz-thread-pool-"));
...
pipel ine.addLast(bizGroup,xHandler);
4. ByteBuf要复用
在handler中使用ByteBuf后需要release掉,会减少ByteBuf对象的大量创建
release的作用:降低GC 新生代
也可以不用手动释放,选择在handler上继承SimpleChannelInboundHandler
这个类,内部已经实现了释放工作。
也可以把msg往后面责任链去传,也可能后续handler需要使用,利用了队尾handler中处理了所有的善后工作
xxx.fireChannelRead(msg);
5. 把一个特别大的任务拆分为几个小任务(例如邮箱拉取10000条邮件)Fork _ Join。
6. 如何避免让你的项目在上线后出现内存泄漏
将程序长时间运行在一个环境下面,做压力测试时时间要长
。
7. 代码中若有大量数据复制的操作,可以利用Netty中的ByteBuf零拷贝机制来实现。
整体架构
推送服务
小结
- 并发连接数主要靠操作系统参数调优
- 吞吐量的提升,主要靠代码处理能力来提升
- 有时候网络和磁盘会成为瓶颈
- 水平扩展,集群的方式是最终方案