您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > JAVA

Java性能之优化RPC网络通信

时间:2019-09-25 09:53:16  来源:  作者:

服务框架的核心

  1. 大型服务框架的核心:RPC通信
  2. 微服务的核心是远程通信服务治理
  • 远程通信提供了服务之间通信的桥梁,服务治理提供了服务的后勤保障
  1. 服务的拆分增加了通信的成本,因此远程通信很容易成为系统瓶颈
  • 在满足一定的服务治理需求的前提下,对远程通信的性能需求是技术选型的主要影响因素
  1. 很多微服务框架中的服务通信是基于RPC通信实现的
  • 在没有进行组件扩展的前提下,Spring Cloud是基于Feign组件实现RPC通信(基于HTTP+JSON序列化)
  • Dubbo是基于SPI扩展了很多RPC通信框架,包括RMI、Dubbo、Hessian等(默认为Dubbo+Hessian序列化)

 

性能测试

基于Dubbo:2.6.4,单一TCP长连接+Protobuf(响应时间和吞吐量更优),短连接的HTTP+JSON序列化

Java性能之优化RPC网络通信

 


Java性能之优化RPC网络通信

 

RPC通信

架构演化

无论是微服务、SOA、还是RPC架构,都是分布式服务架构,都需要实现服务之间的互相通信,通常把这种通信统称为RPC通信

Java性能之优化RPC网络通信

 

概念

  1. RPC:Remote Process Call,远程服务调用,通过网络请求远程计算机程序服务的通信技术
  2. RPC框架封装了底层网络通信序列化等技术
  • 只需要在项目中引入各个服务的接口包,就可以在代码中调用RPC服务(如同调用本地方法一样)

RMI

  1. RMI:Remote Method Invocation
  2. RMI是JDK自带的RPC通信框架,已经成熟地应用于EJBSpring,是JAVA网络分布式应用系统的核心解决方案
  3. RMI实现了一台虚拟机应用对远程方法的调用可以同对本地方法调用一样,RMI封装好了远程通信的具体细节

实现原理

Java性能之优化RPC网络通信

 

  1. RMI远程代理对象是RMI中最核心的组件,除了对象本身所在的虚拟机,其他虚拟机也可以调用此对象的方法
  2. 这些虚拟机可以分布在不同的主机上,通过远程代理对象,远程应用可以用网络协议和服务进行通信

高并发下的性能瓶颈

  1. Java默认序列化
  • RMI的序列化方式采用的是Java默认序列化,性能不好,而且不支持跨语言
  1. TCP短连接
  • RMI是基于TCP短连接实现的,在高并发情况下,大量请求会带来大量TCP连接的创建销毁非常消耗性能
  1. 阻塞式网络IO
  • Socket编程中使用传统的IO模型,在高并发场景下基于短连接实现的网络通信就很容易产生IO阻塞性能将大打折扣

优化路径

TCP / UDP

  1. 网络传输协议有TCPUDP,两个协议都是基于Socket编程
  2. 基于TCP协议实现的Socket通信是有连接
  • 传输数据要通过三次握手来实现数据传输的可靠性,而传输数据是没有边界的,采用的是字节流模式
  1. 基于UDP协议实现的Socket通信,客户端不需要建立连接,只需要创建一个套接字发送数据给服务端
  • 基于UDP协议实现的Socket通信具有不可靠性
  • UDP发送的数据采用的是数据报模式,每个UDP的数据报都有一个长度,该长度与数据一起发送到服务端
  1. 为了保证数据传输的可靠性,通常情况下会采用TCP协议
  • 在局域网且对数据传输的可靠性没有要求的情况下,可以考虑使用UDP协议,UDP协议的效率比TCP协议高
Java性能之优化RPC网络通信

 

长连接

  1. 服务之间的通信不同于客户端与服务端之间的通信
  2. 由于客户端数量众多,基于短连接实现请求,可以避免长时间地占用连接,导致系统资源浪费
  3. 服务之间的通信,连接的消费端不会像客户端那么多,但消费端向服务端请求的数量却一样多
  • 基于长连接实现,可以省去大量建立TCP连接和关闭TCP连接的操作,从而减少系统的性能消耗,节省时间

 

优化Socket通信

  1. 传统的Socket通信主要存在IO阻塞,线程模型缺陷以及内存拷贝等问题,Netty4对Socket通信编程做了很多方面的优化
  2. 实现非阻塞IO:多路复用器Selector实现了非阻塞IO通信
  3. 高效的Reactor线程模型
  • Netty使用了主从Reactor多线程模型
  • 主线程:用于客户端的连接请求操作,一旦连接建立成功,将会监听IO事件,监听到事件后会创建一个链路请求
  • 链路请求将会注册到负责IO操作的IO工作线程上,由IO工作线程负责后续的IO操作
  • Reactor线程模型解决了在高并发的情况下,由于单个NIO线程无法监听海量客户端和满足大量IO操作造成的问题

4.串行设计

  • 服务端在接收消息之后,存在着编码、解码、读取和发送等链路操作
  • 如果这些操作基于并行实现,无疑会导致严重的锁竞争,进而导致系统的性能下降
  • 为了提升性能,Netty采用串行无锁化完成链路操作,提供了Pipeline,实现链路的各个操作在运行期间不会切换线程

5.零拷贝

  • 数据从内存发到网络中,存在两次拷贝,先是从用户空间拷贝到内核空间,再从内核空间拷贝到网络IO
  • NIO提供的ByteBuffer可以使用Direct Buffer模式
  • 直接开辟一个非堆物理内存,不需要进行字节缓冲区的二次拷贝,可以直接将数据写入到内核空间

6.优化TCP参数配置,提高网络吞吐量,Netty可以基于ChannelOption来设置

  • TCP_NODELAY:用于控制是否开启Nagle算法
  • Nagle算法通过缓存的方式将小的数据包组成一个大的数据包,从而避免大量发送小的数据包,导致网络阻塞
  • 在对时延敏感的应用场景,可以选择关闭该算法
  • SO_RCVBUF / SO_SNDBUF:Socket接收缓冲区发送缓冲区的大小
  • SO_BACKLOG:指定客户端连接请求缓冲队列的大小
  • 服务端处理客户端连接请求按顺序处理的,同一时间只能处理一个客户端连接
  • 当有多个客户端进来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理
  • SO_KEEPALIVE
  • 连接会检查长时间没有发送数据的客户端的连接状态,检测到客户端断开连接后,服务端将回收该连接
  • 将该值设置得小一些,可以提高回收连接的效率

 

定制报文格式

  1. 设计一套报文,用于描述具体的校验、操作、传输数据等内容
  2. 为了提高传输效率,可以根据实际情况来设计,尽量实现报体小,满足功能,易解析等特性

字段长度(字节)备注魔数4协议的标识,类似于字节码的魔数,通常为固定数字版本号1序列化算法1Protobuf / Thrift指令1类似于HTTP中的增删改查数据长度4数据N

编解码

  1. 实现一个通信协议,需要兼容优秀的序列化框架
  2. 如果只是单纯的数据对象传输,可以选择性能相对较好的Protobuf序列化,有利于提高网络通信的性能

linux的TCP参数设置

三次握手

Java性能之优化RPC网络通信

 

四次挥手

Java性能之优化RPC网络通信

 

配置项

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.客户端连接服务器时,需要动态分配源端口号,该配置项表示向外连接的端口范围

5. 当一个连接关闭时,TCP会通过四次挥手来完成一次关闭连接操作,在请求量比较大的情况下,消费端会有大量TIME_WAIT状态的连接,该参数可以限制TIME_WAIT状态的连接数量,如果TIME_WAIT的连接数量超过该值,TIME_WAIT将会立即被清除掉并打印警告信息

6.客户端每次连接服务器时,都会获得一个新的源端口以实现连接的唯一性,在TIME_WAIT状态的连接数量过大的情况下,会增加端口号的占用时间,由于处于TIME_WAIT状态的连接属于关闭连接,所以新创建的连接可以复用该端口号



Tags:Java性能优化   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
服务框架的核心 大型服务框架的核心:RPC通信 微服务的核心是远程通信和服务治理 远程通信提供了服务之间通信的桥梁,服务治理提供了服务的后勤保障 服务的拆分增加了通信的成...【详细内容】
2019-09-25  Tags: Java性能优化  点击:(93)  评论:(0)  加入收藏
不同需要性能比较方法放到一个虚拟机里调用,有可能会互相影响。最好的办法是分成俩个独立的进程运行,确保俩个对比方法不相互影响。...【详细内容】
2019-08-27  Tags: Java性能优化  点击:(216)  评论:(0)  加入收藏
▌简易百科推荐
面向对象的特征之一封装 面向对象的特征之二继承 方法重写(override/overWrite) 方法的重载(overload)和重写(override)的区别: 面向对象特征之三:多态 Instanceof关键字...【详细内容】
2021-12-28  顶顶架构师    Tags:面向对象   点击:(2)  评论:(0)  加入收藏
一、Redis使用过程中一些小的注意点1、不要把Redis当成数据库来使用二、Arrays.asList常见失误需求:把数组转成list集合去处理。方法:Arrays.asList 或者 Java8的stream流式处...【详细内容】
2021-12-27  CF07    Tags:Java   点击:(3)  评论:(0)  加入收藏
文章目录 如何理解面向对象编程? JDK 和 JRE 有什么区别? 如何理解Java中封装,继承、多态特性? 如何理解Java中的字节码对象? 你是如何理解Java中的泛型的? 说说泛型应用...【详细内容】
2021-12-24  Java架构师之路    Tags:JAVA   点击:(5)  评论:(0)  加入收藏
大家好!我是老码农,一个喜欢技术、爱分享的同学,从今天开始和大家持续分享JVM调优方面的经验。JVM调优是个大话题,涉及的知识点很庞大 Java内存模型 垃圾回收机制 各种工具使用 ...【详细内容】
2021-12-23  小码匠和老码农    Tags:JVM调优   点击:(12)  评论:(0)  加入收藏
前言JDBC访问Postgresql的jsonb类型字段当然可以使用Postgresql jdbc驱动中提供的PGobject,但是这样在需要兼容多种数据库的系统开发中显得不那么通用,需要特殊处理。本文介绍...【详细内容】
2021-12-23  dingle    Tags:JDBC   点击:(13)  评论:(0)  加入收藏
Java与Lua相互调用案例比较少,因此项目使用需要做详细的性能测试,本内容只做粗略测试。目前已完成初版Lua-Java调用框架开发,后期有时间准备把框架进行抽象,并开源出来,感兴趣的...【详细内容】
2021-12-23  JAVA小白    Tags:Java   点击:(11)  评论:(0)  加入收藏
Java从版本5开始,在 java.util.concurrent.locks包内给我们提供了除了synchronized关键字以外的几个新的锁功能的实现,ReentrantLock就是其中的一个。但是这并不意味着我们可...【详细内容】
2021-12-17  小西学JAVA    Tags:JAVA并发   点击:(11)  评论:(0)  加入收藏
一、概述final是Java关键字中最常见之一,表示“最终的,不可更改”之意,在Java中也正是这个意思。有final修饰的内容,就会变得与众不同,它们会变成终极存在,其内容成为固定的存在。...【详细内容】
2021-12-15  唯一浩哥    Tags:Java基础   点击:(17)  评论:(0)  加入收藏
1、问题描述关于java中的日志管理logback,去年写过关于logback介绍的文章,这次项目中又优化了下,记录下,希望能帮到需要的朋友。2、解决方案这次其实是碰到了一个问题,一般的情况...【详细内容】
2021-12-15  软件老王    Tags:logback   点击:(19)  评论:(0)  加入收藏
本篇文章我们以AtomicInteger为例子,主要讲解下CAS(Compare And Swap)功能是如何在AtomicInteger中使用的,以及提供CAS功能的Unsafe对象。我们先从一个例子开始吧。假设现在我们...【详细内容】
2021-12-14  小西学JAVA    Tags:JAVA   点击:(22)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条