Java NIO通讯框架在电信领域的实践

 
华为电信软件技术架构演进
Java NIO框架在技术变迁中起到的关键做用
 
C和C++主导的第一代架构
 
Spring + Struts + Tomcat 的第二代架构
Java高性能服务端
 
以SOA为中心的第三代架构
当垂直应用愈来愈多,应用之间交互不可避免,将核心业务抽取出来,做为独立的服务,逐渐造成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。
如何整合异构系统,实现高效企业集成,也是一个巨大的挑战,此时,企业服务总线(ESB)是个不错的选择。
 
以分布式、云化为核心的第四代架构
基于X86架构的廉价硬件 + 分布式软件的模式在互联网行业获得了大规模应用,分布式架构日趋成熟。
传统SOA架构中的一些缺陷逐步暴露,例如企业集成总线ESB是实体总线,性能线性扩展能力有限;硬件负载均衡器的压力愈来愈大,不断扩容致使硬件成本增长;随着业务规模的不断增加,传统的数据库、配置中心等逐渐成为单点瓶颈等。
 
咱们须要经过新的分布式架构来解决电信软件面临的成本高、性能没法线性增加等问题,以分布式技术为核心构建的华为分布式中间件应用而生,它主要包括以下组件:
1) 高性能、低时延的分布式服务框架;
2) 分布式消息队列MQ;
3) 分布式缓存;
4) 分布式数据库访问中间件,支持跨库操做,支持异构数据库;
5) 软负载SLB;
6) 分布式日志采集和检索(Flume + ELK);
7) 分布式实时流式计算框架;
8) 分布式消息跟踪系统;
9) 其它……
 
第四代技术架构以分布式、云化为核心,相比于前三代架构,它的核心特性以下:
1) 采用分布式技术构建,全部的中间件都没有单点,支持线性增加和弹性伸缩;
2) 以微服务架构为核心,打造电信领域的DevOps(结合华为PaaS平台);
3) 由传统的SOA Governance 向微服务治理和自治演进,提高服务治理效能;
4) 分布式日志采集 + 实时流式计算框架,更快的故障定界,提高大规模、分布式系统中的运维效率;
5) 业务和数据的拆分,分而治之,经过分布式中间件服务向业务屏蔽拆分细节;
6) 架构云化带来的巨大优点:资源池提高硬件利用率、DevOps提高开发和运维效率、应用和服务的自动弹性伸缩、应用和服务故障自动恢复、高HA、自动化运维等。
 
【以Netty为表明的NIO框架】
传统同步阻塞通讯面临的主要问题以下:
1) 性能问题:一链接一线程模型致使服务端的并发接入数和系统吞吐量受到极大限制;
2) 可靠性问题:因为I/O操做采用同步阻塞模式,当网络拥塞或者通讯对端处理缓慢会致使I/O线程被挂住,阻塞时间没法预测;
3) 可维护性问题:I/O线程数没法有效控制、资源没法有效共享(多线程并发问题),系统可维护性差
 
从上图咱们能够看出,每当有一个新的客户端接入,服务端就须要建立一个新的线程(或者重用线程池中的可用线程),每一个客户端链路对应一个线程。当客户端处理缓慢或者网络有拥塞时,服务端的链路线程就会被同步阻塞,也就是说全部的I/O操做均可能被挂住,这会致使线程利用率很是低,同时随着客户端接入数的不断增长,服务端的I/O线程不断膨胀,直到没法建立新的线程。
 
同步阻塞I/O致使的问题没法在业务层规避,必须改变I/O模型,才能从根本上解决这个问题。
 
基于Reactor模型统一调度的长链接和短链接协议栈,不管是性能、可靠性仍是可维护性,均可以“秒杀”传统基于BIO开发的应用服务器和各类协议栈,这种指标差别本质上是一种技术代差。
 
【从Java 原生NIO到NIO框架】
JAVA 原生NIO类库的复杂性
如今咱们总结一下为何不建议开发者直接使用JDK的NIO类库进行开发,具体缘由以下:
(1)NIO的类库和API繁杂,使用麻烦,你须要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等;
(2)须要具有其余的额外技能作铺垫,例如熟悉java多线程编程。这是由于NIO编程涉及到Reactor模式,你必须对多线程和网路编程很是熟悉,才能编写出高质量的NIO程序;
(3)可靠性能力补齐,工做量和难度都很是大。例如客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常码流的处理等问题,NIO编程的特色是功能开发相对容易,可是可靠性能力补齐的工做量和难度都很是大;
(4)JDK NIO的BUG,例如臭名昭著的epoll bug,它会致使Selector空轮询,最终致使CPU 100%。官方声称在JDK1.6版本的update18修复了该问题,可是直到JDK1.7版本该问题仍旧存在,只不过该BUG发生几率下降了一些而已,它并无被根本解决。
 
 
Netty是业界最流行的NIO框架之一,它的健壮性、功能、性能、可定制性和可扩展性在同类框架中都是数一数二的,它已经获得成百上千的商用项目验证,例如Hadoop的RPC框架avro使用Netty做为底层通讯框架;不少其余业界主流的RPC框架,也使用Netty来构建高性能的异步通讯能力。
 
经过对Netty的分析,咱们将它的优势总结以下:
1) API使用简单,开发门槛低;
2) 功能强大,预置了多种编解码功能,支持多种主流协议;
3) 定制能力强,能够经过ChannelHandler对通讯框架进行灵活地扩展;
4) 性能高,经过与其余业界主流的NIO框架对比,Netty的综合性能最优;
5) 成熟、稳定,Netty修复了已经发现的全部JDK NIO BUG,业务开发人员不须要再为NIO的BUG而烦恼;
6) 社区活跃,版本迭代周期短,发现的BUG能够被及时修复,同时,更多的新功能会加入;
7) 经历了大规模的商业应用考验,质量获得验证。在互联网、大数据、网络游戏、企业应用、电信软件等众多行业获得成功商用,证实了它已经彻底可以知足不一样行业的商业应用了。
 
【Netty的非阻塞I/O调度模型】
 
【高性能的序列化框架】
在华为软件,对于序列化框架的选择,咱们遵循以下几个原则:
1) 序列化后的码流大小(网络带宽的占用);
2) 序列化&反序列化的性能(CPU、内存等资源占用);
3) 是否支持跨语言(异构系统的对接和开发语言切换);
4) 高并发调用时的性能,是否随着线程并发数线性增加。
 
基于上述的指标,目前最经常使用的选择是:Google的ProtoBuf和Apache的Thrift。
 
Netty原生提供了对ProtoBuf序列化框架的支持,它的优势以下:
1) 在谷歌内部长期使用,产品成熟度高;
2) 跨语言、支持多种语言,包括C++、Java和Python;
3) 编码后的消息更小,更加有利于存储和传输;
4) 编解码的性能很是高;
5) 支持不一样协议版本的前向兼容;
6) 支持定义可选和必选字段。
 
Thrift相对复杂一些,须要将编解码框架从Thrift中剥离出来,而后利用Netty编解码框架的扩展性定制实现,在此再也不赘述。
 
【收敛的Reactor线程模型】
若是使用Tomcat等作Web容器,为了保证吞吐量和性能,HTTP线程池的最大线程数每每配置为1024。
在系统运行期间咱们Dump线程堆栈,发现大量的线程竞争,这不只致使HTTP协议栈的性能降低,更影响其它业务处理线程的执行效率。
 
【其它优化】
为了进一步提高性能,下降时延,咱们还采用了其它一些优化措施,总结以下:
1) 使用Netty 4的内存池,减小业务高峰期ByteBuf频繁建立和销毁致使的GC频率和时间;
2) 在程序中充分利用Netty提供的“零拷贝”特性,减小额外的内存拷贝,例如使用CompositeByteBuf而不是分别为Head和Body各建立一个ByteBuf对象;
3) TCP参数的优化,设置合理的Send和Receive Buffer,一般建议值为64K – 128K;
4) 软中断:若是Linux内核版本支持RPS(2.6.35以上版本),开启RPS后能够实现软中断,提高网络吞吐量;
5) 无锁化串行开发理念:使用Netty 4.X版本,天生支持串行化处理;业务开发过程当中,遵循Netty 4的线程模型优化理念,防止人为增长线程竞争。
相关文章
相关标签/搜索