前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go进阶训练营 – 微服务概览与治理三:gRPC & 服务发现

Go进阶训练营 – 微服务概览与治理三:gRPC & 服务发现

作者头像
Yuyy
发布2022-09-21 10:30:20
1.7K0
发布2022-09-21 10:30:20
举报
文章被收录于专栏:yuyy.info技术专栏

什么是gRPC?

  • A high-performance, open-source universal RPC framework。
  • 语言中立,公司里可能存在不同语言的服务需要交互。
    • 统一采用gRPC作为服务之间的通信协议,可能存在其他性能更好的解决方案,但不要过早关注性能问题,先标准化更重要。
  • 轻量级、高性能,序列化比JSON性能好
  • 可插拔,支持插件,例如gRPCGetway插件可以生成http接口,默认只生成gRPC接口。协议可插拔,支持JSON、xml等。
  • IDL:代码即文档,避免接口文档未更新的情况。
  • 快速生成接口服务端、客户端代码,服务端已定义好接口,自己实现下就行。
  • 移动端:基于标准的 HTTP2 设计,支持双向流、消息头压缩、单 TCP 的多路复用、服务端推送等特性,这些特性使得 gRPC 在移动端设备上更加省电和节省网络流量。
    • 数据库连接池产生的原因是协议设计缺陷,具体参照下面的http协议演进
  • 负载无关的:支持 protocol buffers、JSON、XML 和 Thrift。
  • 流:Streaming API,一边传输,一边读取,不用等大文件传输完再读取。
  • 阻塞式和非阻塞式:支持异步和同步处理在客户端和服务端间交互的消息序列。
  • 元数据交换:类似http header,常见的横切关注点,如认证或跟踪,依赖数据交换。
  • 标准化状态码:客户端通常以有限的方式响应 API 调用返回的错误。约束状态码名称空间,以使这些错误处理决策更加清晰。
  • 相对于直接定义restful接口的优势:接口定义更加明确,请求体、响应体通过message定义出来,而直接定义restful接口,体现方式不统一,接口文档(维护性差)?第三方平台?服务端直接定义+swagger?

gRPC - HealthCheck

gRPC 有一个标准的健康检查协议,默认提供用于设置运行状态的功能。

使用示例

  1. 定义健康检查的API
  2. golang使用gRPC健康检查
client
代码语言:javascript
复制
    echoClient := pb.NewEchoClient(conn)
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    r, err := c.UnaryEcho(ctx, &pb.EchoRequest{})
    if err != nil {
        fmt.Println("UnaryEcho: _, ", err)
    } else {
        fmt.Println("UnaryEcho: ", r.GetMessage())
    }
server
代码语言:javascript
复制
healthcheck.SetServingStatus(serverName, healthpb.HealthCheckResponse_SERVING)

健康检查的应用

服务发现双保险

消费者可以直接感知提供者的状态,保障消费者和注册中心网络不稳定的情况下,也能及时将异常服务提供者从本地负载均衡池中移除。同理,提供者正常运行后,也能被消费者感知,重新加入负载均衡池。

应用平滑发布
老版本注销
  1. k8s向注册中心发起注销请求
  2. k8s向容器发送SIGTERM信号,相当于kill命令。
  3. 应用将gRPC服务状态设置为不健康,并等待两个心跳周期,保障那些没有被注册中心通知到的消费者感知到,避免流量进入。
  4. 等待正在处理的请求处理完毕,k8s可以做个兜底,2分钟没退出就强制干掉容器,相当于kill -9 。
  5. 进入优雅退出过程,断开连接之类的。
  6. 退出容器
新版本创建
  1. 创建容器
  2. 通过外挂的方式,检查应用状态。
  3. 应用启动完毕后,设置gRPC服务状态设置为健康。
  4. 外挂的辅助脚本检测到应用健康,进行注册到注册中心。
为什么不是应用自己去注册?

剥离注册功能,下沉到辅助脚本里。避免所有应用(不同语言)都需要配置、提供注册功能。

为什么不直接使用k8s的探针来检测应用健康?

因为k8s 1.23以前不支持检测gRPC服务,只能发送http请求,或者是检测TCP端口的连通性。

k8s 1.23 以前如何检测 gRPC 服务状态?

服务发现 - 客户端发现

由注册中心做服务发现,并下发服务注册表到消费者,负载均衡在客户端完成。

  • 去中心化——微服务核心理念
  • 直连,性能更好
  • 缺点:需要所有应用内置本地负载均衡组件,不同语言的应用,使用的负载均衡组件还不同。可使用service mesh优化,在k8s中使用sidecar来做负载均衡,从应用中独立出来,下沉为单独组件。
  • ribbon就是这么干的,之前有写过博客:【SpringCloud】五、Ribbon

服务发现 - 服务端发现

由注册中心做服务发现,并提供一个负载均衡器,从注册中心查询服务注册信息,客户端统一请求负载均衡器。

  • 类似设计模式里的中介模式的概念。
  • 应用无需关心负载均衡如何实现。
  • 流量热点,如果使用nginx做负载均衡,单个nginx承受不住,还得使用lvs+nginx集群,增加复杂度。
  • 相关实现有:Consul Template+Nginxkubernetes+etcd

服务发现

各注册中心对比

B站为什么从zookeeper切换到eureka?

zk保证了写操作一致性、分区容错。但leader节点挂掉后,会进行选举新的leader节点。期间整个zk是不能对外提供服务,大概会持续几十秒。从而失去可用性。并且大量服务长连接导致性能瓶颈。

而使用gRPC的服务发现这个场景下,一致性是可以弱一点的,带来的影响是:1、消费者没能拿到新注册的提供者地址,那就等一会呗。2、消费者拿到已注销的提供者地址,由于做了gRPC健康检查,并不会去调用该服务,会选择存活的服务。

而eureka就属于AP阵营,保证可用性,没有主节点,其他节点都挂掉,只剩一个节点也能对外提供服务。

服务发现架构

eureka详细介绍

  • 通过 Family(appid) 和 Addr(IP:Port) 定位实例,除此之外还可以附加更多的元数据:权重、染色标签、集群等。
    • appid: 使用三段式命名,business.service.xxx
  • Provider 注册后定期(30s)心跳一次,注册,心跳,下线都需要进行同步,注册和下线需要进行长轮询推送。
    • 新启动节点,需要 load cache,JVM 预热。
    • 故障时,Provider 不建议重启和发布。
      • 某个eurak挂了,不要马上主动重启,因为新启动的enuraka里没有任何服务注册信息,这时候有服务来拉取服务注册信息,就会导致该服务无法访问其他服务。如果立即重启,需要做控制,例如启动后等待数据同步完毕才对外提供服务。
      • 全部eureka节点都挂了,全部重启后,需要等待2、3个心跳周期,等服务都注册好后,在对外提供查询服务。
  • Consumer 启动时拉取实例,发起30s长轮询。故障时,需要 client 侧 cache 节点信息。
    • 长轮询:客户端发送请求拉取数据,如果此时服务端没有产生的数据,就不暂时不响应,等有数据或者达到超时时间(例如30秒),再响应。也就是这个请求会挂起。有效减少轮询场景下的请求数量。
  • Server 定期(60s) 检测失效(90s)的实例,失效则剔除。短时间里丢失了大量的心跳连接(15分钟内心跳低于期望值*85%),开启自我保护,保留过期服务不删除。

B站是重写了eureka,做了这些改进,不清楚这是eureka本身的特性还是B站改进后的。

其他

分布式系统的 CAP 定理

分布式系统的三大指标

Eric Brewer 说,这三个指标不可能同时做到。这个结论就叫做 CAP 定理。

Partition tolerance

分区容错性,多数分布式系统都分布在多个子网络,每个子网络就是一个区。分区容错的意思是,允许区间通信失败,也就是节点之间通信失败。强调节点的独立性。

分布式系统中,网络异常是很难避免的,因此可以认为 CAP 的 P 总是成立。CAP 定理告诉我们,剩下的 C 和 A 无法同时做到。

Consistency

一致性,由于是分布式系统,多节点设计,就得考虑一致性问题,即访问分布式系统,和访问单体应用一样,下一次读操作一定能读到上一次的写操作结果。是不是有点像多线程并发,只是将线程换成了节点。

Availability

可用性,整个分布式系统能正常对外提供服务。

为什么一致性和可用性不能同时满足?

假如节点之间数据同步失败,整个系统还是要对外提供服务,也就是以分区容错为基础。

  • 如果要保证一致性,那么同步失败的节点就不能对外提供服务,得等到数据同步成功才能恢复,失去可用性。
  • 如果保证可用性,那么访问到未同步数据的节点,就会得到脏数据,失去一致性。

所以得结合实际使用场景,在设计阶段,对一致性和可用性进行取舍。

http协议演进

Http 1.0
存在的问题
  • 无法复用链接:每个请求都需要建立TCP链接。
  • 对头阻塞:第二个请求必须等第一个请求响应后才能发起。
Http 1.1
特性
  • 默认使用长连接,可配置Keep-alive来控制连接时间
  • 支持请求管道化,客户端可以发送多个请求,而不用等待前一个请求响应。
存在的问题
  • 为了让客户端识别请求对应的响应,服务端响应时,必须按照请求的顺序进行响应,哪怕第二个响应准备好了,也得等第一个响应先返回。
Http 2.0
特性
  • 采用二进制格式传输数据,而非Http 1.x的文本格式,解析更高效。
  • HTTP 1.x的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP2.0 将请求和响应数据分割为更小的帧,并且它们采用二进制编码,乱序发送,最终组装。
  • 压缩header,并缓存header。
  • 同个域名只需要占用一个TCP连接,使用一个连接并行发送多个请求和响应。
  • 多个请求之间、多个响应之间互不影响,实现并发。
存在的问题
  • 由于复用一个TCP链接,一旦出现丢包,就得重传,后面所有请求都被阻塞。
Http 3.0
特性
  • 谷歌基于UDP 协议来定义的 QUIC 协议,应用到Http 3.0上。
  • 不需要链接,所以没有额外的链接时间。
  • 一个连接上的多个stream之间没有依赖,如果某个Stream丢了一个包,是不影响后续的Stream。
  • 向前纠错:每个数据包除了它本身的内容之外,还包括了部分其他数据包的数据,因此少量的丢包可以通过其他包的冗余数据直接组装而无需重传。
  • 加密认证的报文: TCP协议头部没有经过任何加密和认证,所以在传输过程中很容易被中间网络设备篡改。QUIC 所有报文头部都是经过认证的,报文Body都是经过加密的。
  • QUIC在移动端的表现也会比TCP好。因为TCP是基于IP和端口去识别连接的,这种方式在多变的移动端网络环境下是很脆弱的。但是QUIC是通过ID的方式去识别一个连接,不管你网络环境如何变化,只要ID不变,就能迅速重连上。

如何衡量网络的质量?

带宽

单位时间内传输的数据量。

时延

发送数据到就收数据总共花费的时间,包含发送时延,处理时延(网络设备),排队时延(网络设备),传播时延。

抖动

最大时延与最小时延的差值。

丢包

某些原因下会出现丢包,例如网络阻塞:某个网络设备处理不了这么多数据,有的数据包排队很久了,就可能会被丢掉。

多个微服务共享db

微服务中大部分是独占db,也有sharedatabase的情况,例如:具有高级权限的admin服务和面向用户的服务共享db

网关层如何收敛客户端多版本?

可通过请求的header进行路由

微服务之间的服务调用理论上是有向无环图(DAG, Directed Acyclic Graph),如何避免闭环调用?

通过链路追踪得到服务调用关系图,并在服务调用申请权限时进行阻止。

简单接口也要在BFF层定义吗?

BFF支持直接透传,例如一些简单的接口,不需要在BFF做什么,只需调用业务中台的服务就行。但流量还是不能直接从网关层到业务中台,需要在BFF配置路由,让流量经过BFF再到业务中台。

参考

CAP 定理的含义

分布式系统的CAP理论

Http1.0 1.1 2.0 3.0工作原理探究

9 张动图让网络性能的四大指标:带宽、时延、抖动、丢包

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-6-28 1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是gRPC?
  • gRPC - HealthCheck
    • 使用示例
      • client
      • server
    • 健康检查的应用
      • 服务发现双保险
      • 应用平滑发布
  • 服务发现 - 客户端发现
  • 服务发现 - 服务端发现
  • 服务发现
    • 各注册中心对比
      • B站为什么从zookeeper切换到eureka?
        • 服务发现架构
        • 其他
          • 分布式系统的 CAP 定理
            • Partition tolerance
            • Consistency
            • Availability
            • 为什么一致性和可用性不能同时满足?
          • http协议演进
            • Http 1.0
            • Http 1.1
            • Http 2.0
            • Http 3.0
          • 如何衡量网络的质量?
            • 带宽
            • 时延
            • 抖动
            • 丢包
          • 多个微服务共享db
            • 网关层如何收敛客户端多版本?
              • 微服务之间的服务调用理论上是有向无环图(DAG, Directed Acyclic Graph),如何避免闭环调用?
                • 简单接口也要在BFF层定义吗?
                • 参考
                相关产品与服务
                负载均衡
                负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档