了解了解grpc
了解了解grpc
前言
http2
protocol buffer
grpc 的设计与实现
grpc使用优化
refer
前言
前一段时间因为练车所以没什么时间看文章做笔记,现在车练完了,刚好毕业设计后端的接口大部分都写完了,也刚好后端用的是微服务框架,rpc框架是用grpc,所以就写一篇文章,加深一下印象
使用场景
grpc是由谷歌开发的高性能、开源、通用的rpc框架。grpc的使用场景很多,最常用的是后端服务之间的调用,除此之外,还有移动端、grpc-web,之前实习的公司前后端交互全部都是通过niginx将请求转发到grpc服务端
grpc的组成部分
http2作为网络协议 ptotobuf作为高性能的数据包序列化协议 protoc grpc插件生成客户端、服务端易用的sdk
RTT
RTT ( round trip time ) 可以理解为请求一去一反消耗的时间开销。在无缓存的情况下,一个http请求会经过很多的RTT,例如
1、DNS的请求和应答为一个RTT
2、对http服务器进行tcp连接还需要三次握手的两个RTT
3、http跳https又要三次握手的RTT
4、TLS 的2次RTT
不过上面说到的无缓存和未优化的场景开销,正常都是会有一定缓存和优化的
http2
几个版本的比较
grpc基于http2,在此之前需要顺便提一下http的几个版本的发展。http 1.0、http 1.1、http 2.0
http 1.0
缺点
短连接 http 1.1
优点
相比于 1.0 增加了持久化连接、缓存、更多的header支持、accept-range
缺点
「Head-Of-Line」HOL队头阻塞(no pipelining)
http 1.1 的问题就在于队头阻塞,一个连接只能跑一个请求,在请求没返回数据之前,其他请求不能够占用这个连接。如果你进到页面之后有N个并发请求,那么就需要N个连接,但浏览器对连接数有限制(二级域名、一级域名都有限制)
就算不对conn进行控制,也依旧有几个问题,新的连接要3次握手,tls也要握手,之后还要「经历tcp拥塞控制下的慢启动」。这些连接启动后是否要一直保持?那么保持这些连接对比客户端和服务端都有一定的负担
Http2.0
definition
最小单位是frame,一个请求需要header frame、data frame两个帧。stream是http2抽象的流,每个stream都有id,通过id来区分并发过来的请求
二进制分帧层(压缩)
将header和data进行压缩
多路复用
http2最大的特点就是多路复用。这里的复用不是指传统类似epoll对tcp连接的服用,而是在「协议层的多路复用」,把一个个请求封装成stream流,这些流是可以并发交错请求的,这样就解决了http1.1的队头阻塞的问题
hpack 算法
客户端与服务端根据 RFC 7541 的附录A,维护一份共同的静态字典(Static Table),其中包含了常见头部名及常见头部名称与值的组合的代码;通过传递索引号节省Header头部空间 客户端和服务端根据先入先出的原则,维护一份可动态添加内容的共同动态字典(Dynamic Table); 客户端和服务端根据 RFC 7541 的附录B,支持基于该静态哈夫曼码表的哈夫曼编码(Huffman Coding) Head-of-line Blocking 队头阻塞
虽然说http2解决了htpp1.1由于多个请求都需要顺序的从一个连接发出引发的HOL问题,「但其实http2.0还是会遇到另一种类型的HOL问题」(TCP协议的拥塞控制)
❝HTTP/2 runs over a TCP connection; and due to TCP's congestion control, one lost packet in the TCP stream makes all streams wait until that package is re-transmitted and received.
❞
而解决方法就是使用UDP,这就是HTTP/3协议的QUIC protocol所做的事情,这里就不讲了因为我也没去看过
protocol buffer
protobuf是什么?
「Protocol Buffers」是一种序列化数据结构的协议。对于透过管道(pipeline)或存储资料进行通信的程序开发上是很有用的。这个方法包含一个接口描述语言,描述一些数据结构,并提供程序工具根据这些描述产生代码,用于将这些数据结构产生或解析资料流
为什么选择protobuf?
json
浪费空间、丢失了数据类型、不安全、效率低
thrift
额,grpc、protobuf都是谷歌的,生态较好,thrift来自脸书....(还有个问题是thrift不是基于http2的,现在主流的proxy都要支持http2)
protobuf 类型
类型名称 | 值类型 | 举例 |
---|---|---|
enum | string | "BOOK_ON_SALE" |
map<K,V> | object | {"k": v, ...} |
Repeated V | array | [v, ...] |
bool | True, false | true,false |
string | string | "hello word" |
bytes | base64 string | "shadasohdosadopw" |
Int32,fixed32,uint32 | number | 1,-10,0 |
Int64,fixed64,uint64 | string | 1,-10 |
float,double | Number | 1.1,-10.9.0,NaN,Infinity |
Any | Object | Url,f |
Timestamp | string | 1972-01-01T10:00:20.021Z |
Duration | string | 1.000340012s |
Struct | object | {...} |
Wrapper types | Various types | |
FieldMask | string | |
ListValue | array | [foo,bar,...] |
Value | value | |
NullValue | null | |
Empty | Object | {} |
grpc 的设计与实现
grpc workflow
grpc request
grpc deep request
Header frame metadata in header Service/method in header Data frame protobuf
grpc的四种类型
unary
一去一回
Client streaming
客户端单边推送数据
Server streaming
服务端单边推送数据
Bidi streaming
双向推送流数据
Interceptor 拦截器
一般的微服务框架在使用rpc时基本都有相应的拦截器
Middleware (third party): unary、stream interceptor
client balancer 客户端负载均衡
Rate limiter 限流 circuit breaker 熔断 log wrapper 日志 auth wrapper 认证 try catch recovery
其他特性
metadata、keepalive、reflection grpc client withbalancer 负载均衡 withblock withinsecure waitforready ... grpc server MaxConcurrentStreams IinitialWindowSize InitialConnWindowSize UnknownServiceHandler CustomCodec ...
protoc的使用
protoc --go_out=plugins=grpc:. greeter.proto
grpc 微服务
grpc使用优化
打开多个连接时一定一定一定要使用连接池!!复用连接!
refer
https://community.akamai.com/customers/s/article/How-does-HTTP-2-solve-the-Head-of-Line-blocking-HOL-issue?language=en_US https://zh.wikipedia.org/wiki/HTTP/2 http://xiaorui.cc/archives/7054 https://zh.wikipedia.org/wiki/Protocol_Buffers