憧憬 2018-08-05
1.技术点
1.1 长连接还是短连接?
长连接更加省资源,长连接只有在首次创建或者链路重连才会创建链路,实现多消息复用同一个链路、
1.2 采用BIO还是NIO、?
采用nio,因为nio的多路复用技术,Selector可以管理多个通道Channel,nio的非阻塞更加高效、
1.3 自己研制还是选择开源nio框架
netty已经经过诸多项目的考验,并且API层对底层进行了细节隐藏,更加便捷;
netty解决了java 传统nio的bug;
2.功能设计
2.1服务端的设计
原则:1.服务端只提供上层的API,不与任何协议绑定。
2.服务端提供给用户的API尽量的屏蔽底层的通信细节,防止底层变更引起级联变 更。
3.功能不在于全面,而在于可扩展。
2.2客户端设计:
1.第一步创建Bootstrap实例。
2.初始化TCP链接参数,设置编解码handler和其他业务handler,
3.connect方法发起异步TCP连接操作;
connect为异步链接,程序不会等待。TCP是否连接可以通过返回的ChannelFuture对象来通知连接结果。(同步等待:wait后notify,会有InterruptionException;注册监听器:等待操作完成后异步通知)
4.采用连接监听器的方式,异步通知结果;
5.服务端返回TCP握手应答,矽统回调监听器操作完成接口。
6.操作完成接口中实现的逻辑,通知客户端连接操作完成。
3.可靠性设计
3.1 链路有效性检测
当前流行的做法是:心跳检测
心跳检测的机制:
1.TCP层面:TCP的Keep-Alive;它的作用域是整个TCP协议栈;
2.协议层:主要是长连接连接协议中,例如SMPP协议。
3.应用层:通过各个业务与产品通过约定方式定时给对方发送信条消息。
心跳检测的目的:
确认当前的链路是可用的。
不同的协议,心跳机制:
1.ping-pong型心跳:请求-响应型,一方发出ping,收到信息后立即回复pong;
2.ping-ping型心跳:双方按照约定定时想对方发送ping;属于双向心跳。
心跳检测策略:
1.心跳超时:连续N次未检测到对方发送来的ping或者pong信息,则认为链路失效;
2.心跳失败:读取或者发送消息的时候发生了I/o异常;
无论是超时还是失败,都要关闭链路,并且有客户端发起重连,保证恢复正常。
Netty心跳检测利用链路空闲检测机制实现的,空闲机制分为:
1.读空闲:链路持续时间t没有读取任何消息
2.写空闲:链路持续时间t没有发送消息
3.读写空闲:链路持续时间t没有读或者写消息
Netty默认读写空闲机制;利用netty提供的链路空闲检测机制,可以非常灵活的实现链路空闲时的有效性检测;
3.2 断连重连机制
利用netty的CloseChannel,可以方便的检测链路状态,一旦链路关闭,则可以重连。
3.3 消息缓存重发
我们调用发送消息接口的时候,消息并没真正写入Socket中,而是先放入了nio框架的消息发送队列中,由Reactor线程扫描待发送的消息队列,异步的发送给通信对方;遗憾的是 消息队列中挤压部分消息而此时链路断开,这部分消息就会丢失,netty和mina都没有对 消息缓存和重新发送 进行提供,需要自己封装实现。
基于netty如下:
1)、调用ChannelHandlerContext的write()方法时候,返回ChannelFuture对象,我们在ChannelFuture中注册发送结果监听Listener;
2)、在listener的operationComplete方法中判断操作结果,如果操作不成功,将之前发送的消息添加到重发队列;
3)、链路重连成功之后,根据策略,将缓存队列中的消息重新发送出去。
3.4 资源优雅释放
netty提供了相应的接口和类库进行资源优雅释放
优雅释放:
java优雅停机是通过注册jdk的shutdownHook来实现;当系统受到退出指令的时候,首先标记系统处于退出状态,不再接收新消息,然后积压的信息处理完最后资源回收接口调用销毁资源,最后线程退出执行。
一般优雅退出有时间限制,例如30s。如果还未处理完强制执行kill -9 pid
4 性能设计
4.1 性能差:
1.网络传输问题
BIO通信模型,服务端为请求的线程生成不能与并发访问呈线性关系,所以会发生句柄溢出,线程堆栈溢出等,
2.序列化性能差
Java序列化机制是java内部的一种对象编解码机制,无法跨语言使用;
相较于其他开源序列化框架,java序列化后的码流太大,不利于传输或者存储。
序列化性能差,CPU占有率高
3.线程模型问题
同步阻塞I/O,tcp每个链接占一个线程,阻塞导致线程无法及时释放,导致性能下降;
4.2 通信性能三原则:
1.传输:NIO、 BIO、 AIO
2.协议:相较于公有协议,内部私有协议往往性能被设计的更优。
3.线程:Reactor线程模型的不用,对性能影响很大。
4.3 高性能之道
1)、异步非阻塞通信
netty的I/O线程NioEventLoop由于聚合了多路复用器Selector,可以同时处理很多SocketChannel,这就解决了传统同步阻塞IO一个连接一个线程的模型,架构性能、伸缩性得到了提升。
2)、高效的I/O线程模型
netty支持Reactor单线程模型、Reactor多线程模型、主从Reactor多线程模型
3)、高性能的序列化框架
netty默认提供google的Protobuf的二进制序列化框架。
同时,netty还提供了零拷贝、内存池等性能相关的特性。
想要学习Dubbo框架、zookeper基本原理、redis分布式缓存、JVM性能优化,Nginx+apache+Tomcat集群部署、大数据hadoop,Hbase实时计算spark、storm、数据分析分词和权重等核心技术;需要的可以关注之后私信哈,记得要点赞转发噢!!!