前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >微服务治理框架(C++版)详细设计

微服务治理框架(C++版)详细设计

作者头像
ccf19881030
发布2021-04-19 17:56:04
2.6K0
发布2021-04-19 17:56:04
举报
文章被收录于专栏:ccf19881030的博客

@TOC

微服务治理框架(C++版)详细设计


概述

gRPC 是一款高性能、开源的 RPC 框架,产自 Google,基于 ProtoBuf 序列化协议进行开发,支持多种语言(C++、Golang、Python、Java等) gRPC 对 HTTP/2 协议的支持使其在 Android、IOS 等客户端后端服务的开发领域具有良好的前景。 gRPC 提供了一种简单的方法来定义服务,同时客户端可以充分利用 HTTP2 stream 的特性,从而有助于节省带宽、降低 TCP 的连接次数、节省CPU的使用等。

(1)服务端:服务端需要实现.proto中定义的方法,并启动一个gRPC服务器用于处理客户端请求。gRPC反序列化到达的请求,执行服务方法,序列化服务端响应并发送给客户端。

(2)客户端:客户端本地有一个实现了服务端一样方法的对象,gRPC中称为桩或者存根,其他语言中更习惯称为客户端。客户调用本地存根的方法,将参数按照合适的协议封装并将请求发送给服务端,并接收服务端的响应。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OnrdYDL7-1616151589083)(https://raw.githubusercontent.com/grpc-nebula/grpc-nebula/master/images/grpc_transport.png)]

通信模型示意图

服务端


1. 服务端读取配置

  • 1.1 原理分析

2. Provider注册设计说明

注册示意图
注册示意图
  • 2.5代码修改思路 与原生代码耦合处: 需要在server启动的时候获取服务端口,服务名和方法名,并调用注册接口,此处会影响原生代码。而且同步和异步调用服务启动不同,需要分别获取和添加。

3 服务关闭时,自动注销zk中的Provider信息

4 服务流量控制

5. 服务端配置信息监听

6 服务过时打印告警日志

7 服务注册支持配置自定义IP与端口

  • 场景描述

使用场景1:针对利用Nginx做grpc反向代理的场景,服务提供者可以通过配置文件将Nginx的地址注册到Zookeeper

使用场景2:针对服务器跨网段调用时会被映射为另一个IP的场景,应允许服务将自身地址配置为一个映射的IP

  • 实现思路

在配置文件,增加自定义IP与端口的配置信息

代码语言:javascript
复制
# 可选,类型string,说明:服务注册时指定的IP,优先级高于common.localhost.ip参数
# common.service.ip=

# 可选,类型int,说明:服务注册时指定的端口
# common.service.port=

在服务端向注册中心进行注册时,会将服务真实的IP与端口添加到real.ipreal.port参数中,如果配置了自定义的IP与端口,则使用该配置的IP与端口对服务进行注册;如果未配置,则使用真实的ip与端口进行注册;无论是否有配置,真实的IP与端口都将添加到real.ipreal.port参数中。

  • 相关代码

涉及到的模块与代码:

代码语言:javascript
复制
orientsec-provider 模块:
修改 provider_registry()
添加 orientsec_add_property_into_url_inner()

客户端


1 读取本地的配置文件信息

2. 客户端启动时,注册客户端信息

3. 客户端关闭时,注销客户端信息

4. 基于zookeeper的NameResolver

5. 监听服务端信息

6. 实现客户端对路由规则的解析方法,用来过滤服务端列表

  • 6.1原理分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LIPmpPH6-1616151589085)(https://raw.githubusercontent.com/grpc-nebula/grpc-nebula/master/images/workflow.png “consumer workflow”)]

7. 支持路由规则可以设置为IP段、项目

多条路由规则工作原理:

代码语言:javascript
复制
流程如上流程图所示, 如果多条规则,grpc-c会一条一条的匹配, 对于每一条,客户端先看 =>前面的匹配条件,是不是限制本身的,不是的话,跳过;
是的话,继续看=>后面的 服务端IP过滤条件,对provider 列表中的provider进行遍历过滤,如果是限制访问的,置黑名单标志位。
多条规则是 “与” 的工作模式,有一条限制了访问,就不能访问了。

8. 监听路由规则,获取可访问的服务列表

9. 监听服务端权重信息

10. 监听服务端是否过时

11. 客户端监听配置信息的更新

12. 限制客户端对某个服务每秒钟的请求次数(Requests Per Second)

13. 两种负载均衡模式

  • 13.1 原理分析 支持两种模式:一种是“请求负载均衡”,另一种是“连接负载均衡”。 “请求负载均衡”指的是每次调用服务端都调用负载均衡算法选择一个服务端。“连接负载均衡”指的是,创建通道(Channel)后第一次调用选择服务端之后,一直复用与之前已选定的服务端建立的连接。 默认情况下为“连接负载均衡”。
  • 13.2 实现思路 客户端每次调用服务端时,grpc-c中都会调用 start_pick_locked 方法选择subchannel,及选择服务端发送数据,首先判断当前客户端的负载均衡模式,原生的流程是根据DNS等域名解析器解析出提供服务的endpoint(IP+port),然后根据这些endpoint创建一一对应的subchannel,根据原生的算法进行挑选合适的服务提供端进行调用,并传输数据。如果负载均衡模式为“请求负载均衡”,先调用负载均衡算法重新选择服务端,然后再继续原来的流程。

14. 四种负载均衡算法

14.1原理分析 框架支持以下四种负载均衡算法: (1) 随机算法 pick_first 实现原理:数据集合下标随机数 (2) 轮询算法 round_robin 实现原理:数据集合下标加1,取余运算 (3) 加权轮询算法 weight_round_robin 实现原理:采用ngix的平滑加权轮询算法。 (4) 一致性Hash算法 consistent_hash 实现原理:采用MD5算法来将对应的key哈希到一个具有232)-1的数字空间中。同时,引入虚拟机器节点,解决数据分配不均衡的问题。

14.2实现思路

配置文件:

代码语言:javascript
复制
consumer.loadbalance.mode=request
consumer.default.loadbalance=pick_first

配置文件: consumer.loadbalance.mode=request consumer.default.loadbalance=round_robin

配置文件:

代码语言:javascript
复制
consumer.loadbalance.mode=request
consumer.default.loadbalance=weight_round_robin
//可选,类型int,缺省值100,说明:服务provider权重,是服务provider的容量,在负载均衡基于权重的选择算法中用到
provider.weight= 400 

Note: 根据经验或者服务器性能对所有服务器进行权重估算,处理能力越强,权重(黑体加粗数值)越大。算法会根据配置的权重比进行任务分配,权重越大,被调用的次数越多。

配置文件:

代码语言:javascript
复制
consumer.loadbalance.mode=request
consumer.default.loadbalance=consistent_hash

consumer.consistent.hash.arguments=name,no

15. grpc断线重连指数退避算法支持参数配置功能

  • 15.1原理分析 当grpc连接到服务端发生失败时,通常希望不要立即重试(以避免泛滥的网络流量或大量的服务请求),而是做某种形式的指数退避算法。 相关参数: (1)INITIAL_BACKOFF (第一次失败重试前等待的时间) (2)MAX_BACKOFF (失败重试等待时间上限) (3)MULTIPLIER (下一次失败重试等待时间乘以的倍数) (4)JITTER (随机抖动因子) 其中MAX_BACKOFF的值为120,单位秒,参数值目前是直接“硬编码”在框架中的,为了优化系统性能,支持不同的义务系统配置不同的参数值,将该参数的取值修改为可配置的。
  • 15.2实现思路 在配置文件“dfzq-grpc-config.properties”增加如下参数,修改程序增加对这些配置参数的读取。在框架调用指数退避算法时,参数值优先使用配置文件中的数值:

consumer.backoff.maxsecond =120

16. 服务容错

  • 16.1 原理分析

配置服务调用出错后自动重试次数后,可以启用服务容错功能,当调用某个服务端出错后,框架自动尝试切换到提供相同服务的服务端再次发起请求。

调用某个服务端,如果连续5次请求出错,自动切换到提供相同服务的新服务端。(5这个数值支持配置)

调用某个服务端,如果连续5次请求出错,如果此时没有其他服务端,增加一个惩罚连接时间(例如60s)。

  • 16.2实现思路

定义一个客户端调用服务端出现错误的数据集合:

代码语言:javascript
复制
/**
* 各个【客户端对应服务提供者】服务调用失败次数
* key值为:consumerId@IP:port
* value值为: 失败次数 
* 其中consumerId指的是客户端在zk上注册的URL的字符串形式,@是分隔符,IP:port指的是服务提供者的IP和端口
*/
ConcurrentHashMap<String, AtomicInteger> requestFailures = new ConcurrentHashMap<>();

当客户端调用服务端抛出异常时,将错误次数累加到以上的数据集合中。当客户端调用同一个服务端失败达到5次时,进行以下处理:

如果服务端个数大于1,将出错的服务端从客户端内存中的服务端候选列表中移除,然后重新选择一个服务端;

如果服务端个数为1,先记录一下当前的时间,然后出错的服务端从客户端内存中的服务端候选列表中移除。

如果服务端个数为0,但是注册中心上服务端个数大于0,并且当前时间与从内存中删除服务端的时间差大于惩罚时间时,将注册中心上服务端列表更新到客户端内存中,然后调用负载均衡算法重新选择服务端。

  • 16.3相关代码

涉及到的模块与代码:

代码语言:javascript
复制
orientsec-consumer 模块:
新增 failover_utils类
新增 record_provider_failure()方法
修改 BlockingUnaryCallImpl()方法嵌入调用接口

17. 支持失败服务恢复到服务端列表时间自定义配置

  • 17.1原理分析

调用某个服务端,如果连续出错5次(5次内有一次调用成功,会重置失败次数,以达到连续的效果;5这个数值支持配置),会把该服务从服务端列表中摘除该服务端节点,通过FATAL ERROR信息的日志记录服务调用失败的相关情况;被移除的服务在10分钟后(时间支持配置),自动恢复到服务端列表中。

  • 17.2实现思路

在配置文件,增加服务恢复时间的配置

代码语言:javascript
复制
# 可选,类型integer,缺省值5,说明:连续多少次请求出错,自动切换到提供相同服务的新服务器
# consumer.switchover.threshold=5

# 可选,类型int,说明:服务端节点调用失败被移除请求列表后,经过多长时间将该服务端节点重新添加回服务端候选列表
# 单位毫秒,默认值600000,即600秒,即10分钟
# consumer.service.recoveryMilliseconds=600000

服务调用失败时,比较当前失败服务的调用次数,如果服务端失败达到5次时,进行以下处理:

(1)将该服务从服务端列表中移除,并通过FATAL ERROR信息的日志进行输出;

(2)通过一个延迟执行的线程,在10分钟后,将该服务恢复到服务端列表中;

(3)重置该服务的失败次数,并重选服务提供者。

  • 17.3相关代码

涉及到的模块与代码:

代码语言:javascript
复制
orientsec-grpc-core 模块:
修改 com.orientsec.grpc.consumer.ErrorNumberUtil#recordInvokeInfo
修改 com.orientsec.grpc.consumer.ErrorNumberUtil#removeCurrentProvider
新增 com.orientsec.grpc.consumer.ErrorNumberUtil#resetFailTimes

18. 服务调用出错后支持自动重试

  • 18.1原理分析

当服务调用出错时,可通过配置的重试次数进行重试,调用重试次数的配置支持到服务级别以及服务方法级别;重试次数配置优先级如下:方法级别 > 服务级别 > 默认重试配置

  • 18.2实现思路

在配置文件,增加服务调用重试次数的相关配置,具体如下:

代码语言:javascript
复制
# 可选,类型int,缺省值0,0表示不进行重试,说明:服务调用出错后自动重试次数
# consumer.default.retries=0

# 可选,类型int,说明:指定服务名称的服务调用出错后,自动重试次数,[]中配置指定的服务名称
# consumer.default.retries[helloworld.Greeter]=0

# 可选,类型int,说明:指定服务的方法调用出错后,自动重试次数,[]中配置指定服务名称及方法名
# 最小可到指定到方法名
# consumer.default.retries[helloworld.Greeter.sayHello]=0

当某一服务在调用出错时,框架会进行调用重试,重试的次数根据配置来确定。在进行重试时,会根据当前出错服务的方法、服务名、默认配置来选择重试次数;获取重试次数的优先级:方法级别 > 服务级别 > 默认重试配置,确认重试次数后,会进行服务调用重试。

例:当前服务名:helloworld.Greeter,方法名为sayHello。当sayHello方法调用出错时,优先从配置文件获取consumer.default.retries[helloworld.Greeter.sayHello]属性值作为重试次数进行调用重试;如果未配置,则获取consumer.default.retries[helloworld.Greeter]属性值,若该属性也未配置,则取consumer.default.retries的配置作为重试次数。

  • 18.3相关代码

涉及到的模块与代码:

代码语言:javascript
复制
orientsec-consumer 模块:
修改 BlockingUnaryCall() 判断调用结果,失败的话重新调用

系统组件


1. HTTP/2

  • 1.1 概念 • 消息(Message):由一个或多个帧组合而成,例如请求和响应; • 流(Stream):存在于连接中的一个虚拟通道,流可以承载双向消息,每个流都有一个唯一的整数ID; • 帧(Frame):HTTP/2通信的最小单位,每个帧包含帧首部,至少也会标识出当前帧所属的流; • 连接(Connection):与 HTTP/1 相同,都是指对应的 TCP 连接;
  • 1.2 特征 • 多路复用、乱序收发:可以乱序收发数据报文,不用使用单步:发1->收1 或者流水线:发1->发2->收2->收1 的流程,提高效率; • Header压缩:不用花大量篇幅重复发送常用header,采用发送增量的方法,由客户端和服务器端共同维护一个字典; • stream优先级:可以在一个连接上,为不同stream设置不同优先级; • 服务器推送:提前发送需要的资源;

2. Grpc-c 工作流程

  • 2.1 发送流程 • 解析地址:client消息发送给gRpc,然后resolver解析域名,并获取到目标服务器地址列表; • 负载均衡:客户端基于负载均衡算法,从连接服务器列表中找出一个目标服务器; • 连接:如果到目标服务器已有连接,则使用已有连接,访问目标服务器;如果没有可用连接,则创建HTTP/2连接; • 编码:对请求消息使用 Protobuf做序列化,通过 HTTP/2 Stream 发送给 gRPC 服务端;
  • 2.2 接收流程 • 编码:接收到服务端响应之后,使用Protobuf 做反序列化; • 回调:回调 GrpcFuture 的 set(Response) 方法,唤醒阻塞的客户端调用线程,获取 RPC 响应。
  • 2.3 流程示意图 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tt6KT3xZ-1616151589087)(https://raw.githubusercontent.com/grpc-nebula/grpc-nebula/master/images/index.png “HTTP/2 workflow”)]

3. 支持Zookeeper开启ACL

  • 3.1原理分析 zookeeper是一个高效的分布式协调服务,他暴露了一些共用服务,比如命名、配置、管理、同步控制、群组服务等我们可以使用zk来实现比如打成共识,集群管理、leader选举等。 什么是ACL,Zookeeper作为一个分布式协调框架,其内部存储的都是一些关乎分布式系统运行时状态的元数据,尤其是设计到了一些分布式锁,Master选举和协调应用场景,有效的保障Zookeeper中的数据安全,ZookeeperZK提供了三种模式,权限模式,授权对象,权限权限模式:Scheme 开发人员最多使用的如下四种权限模式
    • IP: ip模式通过ip地址,来进行权限控制
    • Digest: digest是最常用的权限控制模式,zk会对形成的权限标识先后进行两次编码处理,分别是SHA-1加密 算法、BASE64编码。
    • World:World是一值最开放的权限控制模式、这种模式可以看做为特殊的Digest,他仅仅是一个标识而已
    • Super:超级用户模式,在超级用户模式下可以ZK进行操作 权限: 权限就是指那些通过权限检测后可以允许执行的操作,在ZK中,对数据的操作权限分为以下五大类: CREATE、Delete、READ、WRITE、ADMIN permission: zookeeper目前支持下面一些权限:
    • CREATE©: 创建权限,可以在在当前node下创建child node
    • DELETE(d): 删除权限,可以删除当前的node
    • READ®: 读权限,可以获取当前node的数据,可以list当前node所有的child nodes
    • WRITE(w): 写权限,可以向当前node写数据
    • ADMIN(a): 管理权限,可以设置当前node的permission

综合考虑,digest权限控制方案比较适合grpc框架,因此采用这种方案进行访问控制。

如果配置了zookeeper访问控制用户名和密码,那么在创建Zookeeper Client时,增加ACL验证数据。即客户端和服务端访问zookeeper时,需要进行ACL验证。验证失败的情况,无法正常访问服务。

4. 主备切换

  • 4.1 使用场景

多个服务端提供服务的时候,能够区分主服务器和备服务器。当主服务器可用时客户端只能调用主服务器,不能调用备服务器;当所有主服务器不可用时,客户端自动切换到备服务器进行服务调用;当主服务器恢复时,客户端自动切换到主服务器进行服务调用。

  • 4.2 实现思路

给服务端添加一个master属性,用来标识服务端是主服务器还是备服务器,master等于true表示主服务器,master等于false表示备服务器,master缺省时为true。

当客户端启动时,首先根据服务名获取所有的服务端列表,然后根据每个服务端的master属性进行筛选操作:

(1) 当服务端列表中全部都是主服务器的时候,服务端列表不发生变化

(2) 当服务端列表中全部都是备服务器的时候,服务端列表不发生变化

(3) 当服务端列表中既有主服务器也有备服务器的时候,将备服务器从服务列表中移除出去,只保留主服务器

同时,客户端监听注册中心中服务端主备属性的变化,一旦监听到变化,重新获取服务端列表,并进行以上筛选操作。

  • 4.3 相关代码

涉及到的模块和代码:

代码语言:javascript
复制
orientsec-provider 模块:
增加provider的master属性

orientsec-consumer 模块:
修改 consumer_query_providers 函数
增加 master 和 online 属性的判断和解析

5. 支持优先级的服务分组

  • 5.1 使用场景
  • 场景1:服务分组。当服务集群非常大时,客户端不必与每个服务节点建立连接,通过对服务分组,一个客户端只与一个服务组连接。
  • 场景2:业务隔离。例如服务端部署在三台服务器上,分别提供给三种业务的客户端。该场景下,可以将三台服务器配置不同的分组,然后不同业务的客户端配置各自的服务端分组。这样即使其中一种业务的客户端调用频繁导致服务端响应时间边长,也不会影响其它两种业务的客户端。
  • 场景3:多机房支持。例如某证券公司在上海有两个机房A和B,在深圳有一个机房C,三个机房都对外提供服务;每个机房都划分为两个分组,即三个机房共有6个分组,分别为A1、A2、B1、B2、C1、C2。在上海地区的客户端要调用证券公司的服务时,可以优先调用A1、A2两个分组的服务端;如果A1、A2分组的服务端不可用,调用B1、B2两个分组的服务端;如果B1、B2分组的服务端也不可用,调用C1、C2两个分组的服务端。
  • 5.2 实现思路

服务端添加一个group属性,用来标识服务端的服务分组,group缺省值为空,表示没有服务分组。客户端也添加一个group属性,用来标识当前客户端可以调用的服务端分组。

当客户端启动时,首先根据服务名获取所有的服务端列表,然后根据客户端的group属性和每个服务端的group属性,对服务端列表进行筛选操作:

(1) 当客户端group属性为空的时候,服务列表不发生变化

(2) 当客户端group属性不为空的时候,首先获取高优先级分组的服务端,如果获取不到,再获取优先级低的服务端。只要某个优先级分组的服务端获取到,就将获取到的服务端作为客户端的服务端列表。如果所有的优先级的分组服务端都没有获取到,客户端报错,提示找不到服务端。

同时,客户端监听注册中心中服务端和客户端分组的变化,一旦监听到变化,重新获取服务端列表,并进行以上筛选操作。 客户端与服务端允许对指定服务名的分组进行单独配置,配置项如下所示:

代码语言:javascript
复制
# 客户端consumer 在中括号[]中配置指定服务的服务名
consumer.invoke.group[helloworld.Greeter]=A1

# 服务端provider 在中括号[]中配置指定服务的服务名
provider.group[helloworld.Greeter]=B1

指定服务名的配置方式优先级高于未指定服务名的配置方式。

例:服务名为A的服务进行注册时,如果同时配置了group与group[A]两个属性,优先取group[A]的属性值作为服务的分组信息,同时如果有服务名为B的服务进行注册时,因为没有配置group[B]这个属性,所以会取group的属性值作为服务的分组信息。

  • 5.3 相关代码

涉及到的模块和代码:

代码语言:javascript
复制
orientsec-consumer 模块:  
新增 orientsec_grpc_consumer_control_group.cc
修改 consumer_query_providers 函数
增加group属性的比对和解析

6. 实现系统内部grpc服务与系统外部grpc服务的区分

  • 6.1使用场景

支持同一项目不同类型的grpc服务具有不同的可见性。

项目中可能会包括两类grpc服务,对于内部项目组件间grpc调用服务,此类服务并不对外暴露,因此应该避免外部项目可见;对于项目对外提供的grpc服务则需要允许外部系统可见。

  • 6.2实现思路

公共注册中心参数配置包括:注册中心集群地址、注册根路径、digest模式ACL的用户名、digest模式ACL的密码。参数名称如下:

代码语言:javascript
复制
zookeeper.host.server (zookeeper.host.server和zookeeper.private.host.server至少配置一个参数)
common.root           (可选参数,默认值/Application/grpc)
zookeeper.acl.username(可选参数)
zookeeper.acl.password(可选参数)

私有注册中心参数配置包括:注册中心集群地址、注册根路径、digest模式ACL的用户名、digest模式ACL的密码。参数名称如下:

代码语言:javascript
复制
zookeeper.private.host.server (zookeeper.host.server和zookeeper.private.host.server至少配置一个参数)
zookeeper.private.root        (可选参数,默认值/Application/grpc)
zookeeper.private.acl.username(可选参数)
zookeeper.private.acl.password(可选参数)

如果服务端所有的服务都是公共服务(外部服务),只需要配置“公共注册中心参数”。

如果服务端所有的服务都是私有服务(内部服务),只需要配置“私有注册中心参数”。

如果服务端同时存在公共服务、私有服务,“公共注册中心参数”和“私有注册中心参数”都需要配置。

如果客户端只调用公共服务(外部服务),只需要配置“公共注册中心参数”。

如果客户端只调用私有服务(内部服务),只需要配置“私有注册中心参数”。

如果客户端同时调用公共服务、私有服务,“公共注册中心参数”和“私有注册中心参数”都需要配置。

如果系统存在私有服务(内部服务),需要配置哪些服务属于私有服务、哪些服务属于公共服务。

参数public.service.list表示公共服务名称列表,多个服务名称之间以英文逗号分隔。该参数可选,如果不配置,表示所有服务都是公共服务。

参数private.service.list表示私有服务名称列表,多个服务名称之间以英文逗号分隔。该参数可选,如果不配置,将公共服务名称列表之外的服务都视为私有服务。

公共服务向公共注册中心上注册,私有服务向私有注册中心上注册。

给服务端增加一个服务类型(service.type)(公共/私有)的属性,服务类型根据服务所在的注册中心来判断,在公共注册中心上的服务为共有服务,在私有注册中心上的服务为私有服务。

  • 注册中心管理方案

公共注册中心集群、私有注册中心集群分开管理。

公共注册中心集群服务注册路径统一为/Application/grpc,并且不设置访问控制权限。

私有注册中心集群服务注册路径为/Application/grpc/private/xxx,xxx表示应用(或开发团队)。区分内外部服务的应用首先需要向zookeeper管理员申请私有注册中心的服务注册路径。

对于私有注册中心集群,不同应用(或开发团队)申请不同的注册路径,zookeeper管理员给不同注册路径设置不同访问控制权限(digest模式)。

对于私有注册中心集群,为了方便服务治理平台管理注册中心,zookeeper管理员将服务治理平台服务器的IP地址列表配置到每个私有注册路径节点的ACL中,实现服务治理平台可以免密访问私有注册中心集群。

  • 6.3相关代码

涉及到的模块和代码:

代码语言:javascript
复制
orientsec-registry 模块:    
修改 orientsec_grpc_registry_zk_intf_init()
修改 registry(url_t* url)
新增 zk_prov_reg_init()
新增 zk_cons_reg_init() 

7. 支持注册中心断线自动重连最长时间配置

  • 7.1原理分析

控制zookeeper的断线重连时间

  • 7.2实现思路

配置文件中增加zookeeper断线重连最长时间配置项。

代码语言:javascript
复制
# 可选,类型int,缺省值30,单位天,即缺省值30天,说明:ZK断线重连最长时间
# zookeeper.retry.time=30

修改创建Zookeeper Client的代码,根据配置的重连最长时间计算重连的次数,创建重试指定次数的重试策略(RetryNTimes),在创建Zookeeper Client选用该重试策略并启用。

  • 7.3相关代码

涉及到的模块与代码:

代码语言:javascript
复制
orientsec-registry 模块:
修改 zk_conn_watcher_g()

8. 注册中心容灾、降级

  • 8.1功能描述 容灾:注册中心不可用时服务端和客户端可以正常启动,注册中心恢复后注册信息需要自动注册到注册中心 降级:客户端可以通过配置文件指定服务端地址,此时即使注册中心不可用,客户端也可以访问服务端;这种情况下,注册中心即使恢复,也不会再去访问注册中心获取最新的服务列表
  • 8.2实现思路 (1)服务端启动时,将自动向zk注册Provider信息的任务代码提取到一个新的线程 (2)客户端启动时,将自动向zk注册Consumer信息的任务代码提取到一个新的线程 (3)获取配置文件中(service.server.list)提供服务的服务器地址列表:如果不为null,将服务提供者存入allProviders、serviceProviderMap中,客户端进行服务调用(忽略注册中心);否则客户端注册zk,获取zk的服务提供者列表进行服务调用 (4)特别注意:一旦配置service.server.list参数,客户端运行过程中,即使注册中心恢复可用,框架也不会访问注册中心。如果需要从配置中心查找服务端信息,需要注释掉该参数,并重启客户端应用。
  • 8.3配置方法

在配置文件“dfzq-grpc-config.properties”增加如下配置:

代码语言:javascript
复制
# 可选,类型string,说明:该参数用来手动指定提供服务的服务器地址列表。
# 使用场合: 在zookeeper注册中心不可用时,通过该参数指定服务器的地址;如果有多个服务,需要配置多个参数。
# 特别注意: 一旦配置该参数,客户端运行过程中,即使注册中心恢复可用,框架也不会访问注册中心。
#           如果需要从配置中心查找服务端信息,需要注释掉该参数,并重启客户端应用。
# xxx表示客户端调用的服务名称
# service.server.list[xxx]=10.45.0.100:50051
service.server.list[xxx]=10.45.0.100:50051,10.45.0.101:50051,10.45.0.102:50051
  • 8.4相关代码

涉及到的模块和代码:

代码语言:javascript
复制
新增 obtain_appointed_provider_list()   
新增 init_provider_from_appointed_list()
新增 init_provider_by_host_port()
修改 orientsec_grpc_consumer_register()

9. 打印log到指定文件

demo-sync-client.cpp:

代码语言:javascript
复制
int main(int argc, char** argv) {
// Instantiate the client. It requires a channel, out of    which the actual RPCs
// are created. This channel models a connection to an endpoint (in this case,
// localhost at port 50051). We indicate that the channel isn't authenticated
// (use of InsecureChannelCredentials()).
//gpr_set_log_verbosity(GPR_LOG_SEVERITY_INFO);
//gpr_set_log_verbosity(GPR_LOG_SEVERITY_ERROR);
//gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG);

// set log output target
gpr_set_log_target(GPR_LOG_WIN_TO_FILE);

gpr_thd_id thd_id;
//开启n线程并发调用
for (int i = 0; i < 1; i++) {
	gpr_thd_new(&thd_id, multiple, NULL, NULL);
}
getchar();

return 0;
}

默认输出到std,即不调用上述API(gpr_set_log_target).

调用如上API,相当于打开log开关,默认会将error log 输出到 client.exe 同目录下 //logs//nebula.log 文件中,方便调查问题。

10. 程序健壮性

当服务端与zookeeper断开连接、服务注册信息丢失后,如果客户端与服务端连接正常,那么客户端与服务端依然可以正常通信。

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 微服务治理框架(C++版)详细设计
    • 概述
      • 1. 服务端读取配置
      • 2. Provider注册设计说明
  • 服务端
    • 3 服务关闭时,自动注销zk中的Provider信息
      • 4 服务流量控制
        • 5. 服务端配置信息监听
          • 6 服务过时打印告警日志
            • 7 服务注册支持配置自定义IP与端口
            • 客户端
              • 1 读取本地的配置文件信息
                • 2. 客户端启动时,注册客户端信息
                  • 3. 客户端关闭时,注销客户端信息
                    • 4. 基于zookeeper的NameResolver
                      • 5. 监听服务端信息
                        • 6. 实现客户端对路由规则的解析方法,用来过滤服务端列表
                          • 7. 支持路由规则可以设置为IP段、项目
                            • 8. 监听路由规则,获取可访问的服务列表
                              • 9. 监听服务端权重信息
                                • 10. 监听服务端是否过时
                                  • 11. 客户端监听配置信息的更新
                                    • 12. 限制客户端对某个服务每秒钟的请求次数(Requests Per Second)
                                      • 13. 两种负载均衡模式
                                        • 14. 四种负载均衡算法
                                          • 15. grpc断线重连指数退避算法支持参数配置功能
                                            • 16. 服务容错
                                              • 17. 支持失败服务恢复到服务端列表时间自定义配置
                                              • 18. 服务调用出错后支持自动重试
                                          • 系统组件
                                            • 1. HTTP/2
                                              • 2. Grpc-c 工作流程
                                                • 3. 支持Zookeeper开启ACL
                                                  • 4. 主备切换
                                                    • 5. 支持优先级的服务分组
                                                      • 6. 实现系统内部grpc服务与系统外部grpc服务的区分
                                                        • 7. 支持注册中心断线自动重连最长时间配置
                                                          • 8. 注册中心容灾、降级
                                                            • 9. 打印log到指定文件
                                                              • 10. 程序健壮性
                                                              相关产品与服务
                                                              负载均衡
                                                              负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
                                                              领券
                                                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档