蚂蚁金服SOFAMesh多协议通用解决方案x-protocol介绍系列
这几天MySQL的东西看的烦了,有些倦怠,看看服务通讯方面的东西换换脑子。
服务调用或者说RPC的协议真的是挺重要的一个点,REST Http1.1,Dubbo,还有其他基于Netty玩的通信比如Lettuce等等,总之给我启发很大。感觉之前关于服务通信协议、io、线程和连接的一些零散的理解的和不理解的点慢慢的清晰串起来了。
SOFAMesh中的多协议通用解决方案x-protocol介绍系列(1) : DNS通用寻址方案 (qq.com)
Dubbo、HSF面向SOA风格的架构和微服务在接入ServiceMesh改造过程中的不同。单进程多接口,单进程单服务。
蚂蚁的这个通用寻址方案是综合参考了K8s和Istio的方案的:
K8s服务调用寻址方式
服务端对应Cluster IP、生成DNS域名给客户端调用,客户端发请求和接受响应之前通过kube-proxy转换。客户端不可见服务端真实IP,服务端不可见Cluster IP
上面原文中有1处笔误:
重点关注请求和应答报文的源地址和目标地址:
- 客户端发出的请求,为“客户端到 ClusterIP”
- kube-proxy 拦截到请求后,将请求修改为“客户端到服务器端”
- 服务器端收到请求时,表现为“客户端到服务器端”,ClusterIP 被kube-proxy 屏蔽
- 服务器端发送应答,因为收到的请求看似来自客户端,因此应答报文为”服务器端到客户端”
- 应答报文被 kube-proxy 拦截,将应答修改为 “ClusterIP到
服务器客户端” - 客户端收到应答,表现为“ClusterIP 到
服务器客户端”,服务器端 IP 被 kube-proxy 屏蔽
Istio的DNS寻址方式
Istio感觉就是基于k8s之上做的,与k8s的服务调用方式非常类似,区别就是把kube-proxy换成所谓sidecar(默认是Envoy),然后部署在客户端pod里边了,然后服务端也需要一个sidecar,sidecar通过Pilot下发的virtual Host配置、然后根据客户端传过来的Cluster IP进行匹配、得到服务端的地址。
然后所谓蚂蚁通用DNS寻址方案没仔细看,应该就是如何在Istio的大框架下,同时还要兼容各种非微服务的遗留项目,同时还要兼容多种RPC协议调用、比如Dubbo、HSF、SOFA等。
SOFAMesh中的多协议通用解决方案x-protocol介绍系列(2):快速解码转发 (qq.com)
协议层面的优化,连接的多路复用,然后精心设计协议,head + length + payload,尽量减少proxy转发时花费在解析上的消耗。同时比较了HSF协议、 bolt协议和dubbo协议、HTTP/2以及HTTP/1.1
SOFAMesh中的多协议通用解决方案x-protocol介绍系列(3)——TCP协议扩展 - 知乎 (zhihu.com)
蚂蚁金服大规模微服务架构下的Service Mesh探索之路 (qq.com)
HTTP/2: The Dark Side of Moon - 知乎 (zhihu.com)
关于HTTP/2以及这玩意扩展出来的谷歌亲儿子gRPC,还有些不是很理解。
HTTP1.1, Http/2, HTTP/3之比较
HTTP1.1
在世纪之交千禧年左右发布的,相对于1.0来说提供了Keep-Alive长连接机制,可以做到连接复用,一般是做连接池模式,连接被线程使用的时候是线程独占的、用完之后归还回池供下次复用。不用每次通信都建立一次连接进行通信然后关闭,大大提升了通信效率。
HTTP/2
在15年发布,18年左右开始流行,提供了连接的多路复用机制,多个请求线程可以同时共享1个物理的TCP连接,非独占式复用。共享物理连接的过程中,每个请求线程发出的请求是可以通过称为Stream的逻辑连接来保证顺序性的。另外在传输数据上,与HTTP1.1使用明文文本不同,HTTP/2使用的是二进制分帧传输,且基于TLS做了加密。
HTTP/2的问题或者说可优化空间在于,其底层使用的TCP协议存在队头阻塞问题,即多个请求打散为二进制帧通过1个TCP连接传输过程中,如果中间某个帧丢包了,那么排队在其后面的所有的包都需要等待重传。从另一个角度看,上层应用层协议HTTP/2通过多路复用和分帧打散传输试图解决之前后一个请求必须等前一个请求返回才能发送的排队现象,在传输层又给打回了原形,TCP的顺序性设计保证是没法绕开的。更糟糕的是,由于HTTP/2一般使用1个连接进行共享,一旦发生上述的队头阻塞问题相对于HTTP1.1的使用多个连接来说带来的影响更大,好歹HTTP1.1还有其他多个连接通道,HTTP/2就是整个通信全被阻塞了。
另外,TCP连接准备阶段要经过3次握手,加上HTTP/2的TLS安全加密要求,这过程中要经过3、4个RTT(Round-Trip Time)的往返时间。
于是,在谷歌的QUIC基础上,HTTP over QUIC即HTTP/3
于2018年又推出了,没错,就是HTTP/2刚开始流行的时候。底层传输层不用TCP了,而是用的UDP协议。其着重解决了上面提到的HTTP/2的两个问题,丢包只会阻塞其自己的这个Stream逻辑连接,同一物理连接上的其他逻辑连接流不受影响。另外,由于基于的是QUIC和UDP协议,所以提供了快速握手连接建立的功能,只需要0、1RTT即可建立通信。
参考
Java 9 和Spring Boot 2.0纷纷宣布支持的HTTP/2到底是什么?
HTTP/2做错了什么?刚刚辉煌2年就要被弃用了!?
Google、Facebook等均开始支持的HTTP3到底是个什么鬼?
?解读HTTP/3
一文读懂 HTTP/1HTTP/2HTTP/3 - 知乎 (zhihu.com)
HTTP/2: The Dark Side of Moon - 知乎 (zhihu.com) HTTP/2不好的一面
nginx反向代理http2? - 知乎 (zhihu.com) 介绍为啥nginx到上游服务器不使用HTTP/2 (但作为web服务器对浏览器支持HTTP/2是有收益的,页面图片多、静态资源多的情况)
关于要不要用HTTP/2 ?
在前端浏览器和web服务器之间做通信,HTTP/2还是有甜头的,特别是页面上需要加载比较多静态资源的时候、比如很多图片等,HTTP/2可以连接共享、不用像HTTP1.1一样受限于浏览器规定的几个连接通道,但是前提是浏览器对于资源加载的顺序要设定的足够合理,因为底层还是TCP,出现队头阻塞问题影响要比多通道的HTTP1.1要影响更严重。另外头压缩也确实可以省一些带宽来着。
两个Servlet后端服务之间进行调用,连接共享模式与池化的独占连接模式相比,好处在于可以少创建连接,然后后端之间内网调用、网络质量丢包之类可以保证,不需要去操心调连接池的连接数配置了,架构可伸缩性好。但要配合线程的非阻塞I/O使用才能充分发挥这个优点,不然线程数资源会先到达瓶颈。
HTTP/2 Gateway (nginx.org)
nginx反向代理http2? - 知乎 (zhihu.com)
HTTP/2 in Netty | Baeldung
再说Spring boot 2.0 与 HTTP/2 - 简书 (jianshu.com)