Java性能之优化RPC网络通信
副标题[/!--empirenews.page--]
服务框架的核心
服务的拆分增加了通信的成本,因此远程通信很容易成为系统瓶颈
很多微服务框架中的服务通信是基于RPC通信实现的
性能测试 基于Dubbo:2.6.4,单一TCP长连接+Protobuf(响应时间和吞吐量更优),短连接的HTTP+JSON序列化 ![]() ![]() RPC通信 架构演化 无论是微服务、SOA、还是RPC架构,都是分布式服务架构,都需要实现服务之间的互相通信,通常把这种通信统称为RPC通信 ![]() 概念
RMI
实现原理 ![]() RMI远程代理对象是RMI中最核心的组件,除了对象本身所在的虚拟机,其他虚拟机也可以调用此对象的方法 这些虚拟机可以分布在不同的主机上,通过远程代理对象,远程应用可以用网络协议和服务进行通信 高并发下的性能瓶颈 Java默认序列化 RMI的序列化方式采用的是Java默认序列化,性能不好,而且不支持跨语言 TCP短连接 RMI是基于TCP短连接实现的,在高并发情况下,大量请求会带来大量TCP连接的创建和销毁,非常消耗性能 阻塞式网络IO Socket编程中使用传统的IO模型,在高并发场景下基于短连接实现的网络通信就很容易产生IO阻塞,性能将大打折扣 优化路径 TCP / UDP 网络传输协议有TCP和UDP,两个协议都是基于Socket编程 基于TCP协议实现的Socket通信是有连接的 传输数据要通过三次握手来实现数据传输的可靠性,而传输数据是没有边界的,采用的是字节流模式 基于UDP协议实现的Socket通信,客户端不需要建立连接,只需要创建一个套接字发送数据给服务端 基于UDP协议实现的Socket通信具有不可靠性 UDP发送的数据采用的是数据报模式,每个UDP的数据报都有一个长度,该长度与数据一起发送到服务端 为了保证数据传输的可靠性,通常情况下会采用TCP协议 在局域网且对数据传输的可靠性没有要求的情况下,可以考虑使用UDP协议,UDP协议的效率比TCP协议高 ![]() 长连接 服务之间的通信不同于客户端与服务端之间的通信 由于客户端数量众多,基于短连接实现请求,可以避免长时间地占用连接,导致系统资源浪费 服务之间的通信,连接的消费端不会像客户端那么多,但消费端向服务端请求的数量却一样多 基于长连接实现,可以省去大量建立TCP连接和关闭TCP连接的操作,从而减少系统的性能消耗,节省时间 优化Socket通信 传统的Socket通信主要存在IO阻塞,线程模型缺陷以及内存拷贝等问题,Netty4对Socket通信编程做了很多方面的优化 实现非阻塞IO:多路复用器Selector实现了非阻塞IO通信 高效的Reactor线程模型 Netty使用了主从Reactor多线程模型 主线程:用于客户端的连接请求操作,一旦连接建立成功,将会监听IO事件,监听到事件后会创建一个链路请求 链路请求将会注册到负责IO操作的IO工作线程上,由IO工作线程负责后续的IO操作 Reactor线程模型解决了在高并发的情况下,由于单个NIO线程无法监听海量客户端和满足大量IO操作造成的问题 4.串行设计 服务端在接收消息之后,存在着编码、解码、读取和发送等链路操作 如果这些操作基于并行实现,无疑会导致严重的锁竞争,进而导致系统的性能下降 为了提升性能,Netty采用串行无锁化完成链路操作,提供了Pipeline,实现链路的各个操作在运行期间不会切换线程 5.零拷贝 数据从内存发到网络中,存在两次拷贝,先是从用户空间拷贝到内核空间,再从内核空间拷贝到网络IO NIO提供的ByteBuffer可以使用Direct Buffer模式 直接开辟一个非堆物理内存,不需要进行字节缓冲区的二次拷贝,可以直接将数据写入到内核空间 6.优化TCP参数配置,提高网络吞吐量,Netty可以基于ChannelOption来设置
定制报文格式 设计一套报文,用于描述具体的校验、操作、传输数据等内容 为了提高传输效率,可以根据实际情况来设计,尽量实现报体小,满足功能,易解析等特性 字段长度(字节)备注魔数4协议的标识,类似于字节码的魔数,通常为固定数字版本号1序列化算法1Protobuf / Thrift指令1类似于HTTP中的增删改查数据长度4数据N 编解码 实现一个通信协议,需要兼容优秀的序列化框架 如果只是单纯的数据对象传输,可以选择性能相对较好的Protobuf序列化,有利于提高网络通信的性能 Linux的TCP参数设置 三次握手 ![]() 四次挥手 ![]() 配置项 1.fs.file-max = 194448 / ulimit 2.net.ipv4.tcp_keepalive_time 3.net.ipv4.tcp_max_syn_backlog 4.net.ipv4.ip_local_port_range 5.net.ipv4.tcp_max_tw_buckets 6.net.ipv4.tcp_tw_reuse 备注 1.Linux默认单个进程可以打开的文件数量上限为1024,Socket也是文件 2.与Netty的SO_KEEPALIVE配置项的作用一致 3.SYN队列的长度,加大队列长度,可以容纳更多等待连接的网络连接数 4.客户端连接服务器时,需要动态分配源端口号,该配置项表示向外连接的端口范围 (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |