1.基本概念
微服务引入的新问题
- 服务单独部署后,引入服务跨网络通信的问题
- 拆分成多个小服务之后,服务如何治理的问题
网络通信的核心组件:RPC框架
RPC框架可以在超时方面有所限制(服务超时,服务降级,服务限流)
2.PRC
设计思路:
- 选择合适的网络模型,有针对性地调整网络参数优化网络传输性能
- 选择合适的序列化方式,以提升封包、解包的性能
PRC通过网络服务调用部署在另一台机器上服务的技术(下游也需要提供一个跨进程通信的端口(将服务运行在进程之上))
| RMI | Web Service | Dubbo | Grpc | |
|---|---|---|---|---|
| 简介 | Java原生的远程调用框架 | HTTP+SOAP 协议 跨语言、跨平台 | ||
| 优点 | ||||
| 缺点 | 1.JRMP通信协议限制只能在Java语言中通信,无法跨语言通信 2.使用远程对象徐内化方式,生成的直接数组空间叫法,效率很差 |
拆分的越多,网络调用的次数就越多
RPC调用过程
- 客户端将调用的类名、方法名、参数名、参数值等信息序列化成二进制流
- 将客户端二进制流通过网络发送到服务端
- 服务端通过序列化协议将二进制流反序列化成调用的类名,方法名,参数名和参数值,再通过动态代理方式获取计算结果
- 服务端将返回值序列化,再通过网络发送给客户端
- 客户端对结果反序列化后可以调用结果
提升RPC性能=网络传输+序列化
2.1如何提升网络传输性能
2.1.1选择高性能IO模型
IO模型:处理IO时的方式
一般会将IO请求分为两个阶段:
IO:I(从1号介质取数据)+O(将数据写入2号媒介)
例如(一个网络请求会有多次IO):
- 从网卡(硬件)将请求IO到socket中(第一次IO)
- 将socket中的请求IO到内存中(第二次IO)
- 将磁盘文件字节流IO到内存中(第三次IO)
- 将内存中的字节流IO到socket中(第四次IO)
- 将socket的字节流IO到网卡(硬件)中(第四次IO)
IO的两阶段=等待资源阶段+使用资源阶段
等待资源阶段:
处理方式=阻塞(死等数据)(数据不可用时IO一直阻塞,直到数据返回)+非阻塞(等数据通知)(数据不可用时IO请求立即返回,直到通知资源可用为止)
使用资源阶段(将接收到的请求数据拷贝到缓冲区中(内存中)):
同步处理(等处理结束)(读取和写入数据时阻塞,直到读取或者写入数据完成)+异步处理(等处理完成同志式)(读取或者写入数据时立即返回,通知应用请求执行完成)
将四种处理方式进行排列组合,得到5中IO模型
- 同步阻塞 I/O:你站在灶台边上一直等着(等待资源)水烧开,然后倒水(使用资源)
- 同步非阻塞 I/O:在烧水的时候躺在沙发上看会儿电视(不再时时刻刻等待资源),但是还是要时不时地去看看水开了没有,一旦水开了,马上去倒水(使用资源)
- 同步多路 I/O 复用:同时烧好多壶水,那你就在看电视的间隙去看看哪壶水开了(等待多个资源),哪一壶开了就先倒哪一壶
- 信号驱动 I/O:不过你发现自己总是跑厨房去看水开了没,太累了,于是你考虑给你的水壶加一个报警器(信号),只要水开了就马上去倒水
- 异步 I/O:智能水壶,在水烧好后自动就可以把水倒好
广泛使用的是多路IO复用:select、epoll 等系统调用都是支持多路 I/O 复用模型的,Java 中的高性能网络框架 Netty 默认也是使用这种模型(Nginx)
通知监听多个请求数据,对其进行相关处理
2.1.2进行一些网络调优
tcpdump抓包用
tcp_nodelay
Nagle`s 算法
如果是连续的小数据包,大小没有一个 MSS(Maximum SegmentSize,最大分段大小),并且还没有收到之前发送的数据包的 Ack 信息,那么这些小数据包就会在发送端暂存起来,直到小数据包累积到一个 MSS,或者收到一个 Ack 为止。
DelayedACK 的超时时间默认是 40ms,所以一旦到了 40ms,接收端回给发送端 ACK,那么发送端才会发送第二个包,这样就增加了延迟。
在 Socket 上开启 tcp_nodelay ,这个参数关闭了 Nagle`s 算法,这样发送端就不需要等到上一个发送包的 ACK 返回直接发送新的数据包就好了。这对于强网络交互的场景来说非常的适用
2.2合适的序列化方法
序列化:将传输对象转换成二进制串的过程
反序列化:将二进制串转换成对象
选择序列化方法的考虑点:
- 时间上开销
- 空间上开销
- 跨语言,跨平台
- 扩展性
| json | thrift | protobuf | |
|---|---|---|---|
| 简介 | 起源于 JavaScript 是一种最广泛使用的序列化协议 | 是 Facebook 开源的高性能的序列化协议,也是一个轻量级的 RPC 框架 | 是谷歌开源的序列化协议 |
| 特点 | 不需要引入IDL | 需要引入IDL | 需要引入IDL |
| 备注 | 游戏公司 可以用于response,由客户端再反序列化一次 | ||
| 场景 | 性能要求不高,宽带不大的情况下 | 对性能有要求 有成熟的一体化方案 | 对性能有要求 对存储有要求的情况下 |
3总结
选择高性能的IO模型:同步多路IO复用模型
调整网络参数:比如将 tcp_nodelay 设置为 true
根据业务实际场景选择序列化手段:性能不高选json,否则Thrift和Portobuf选一个