系统健康度检查系统

290 阅读9分钟

一、背景

独自利用自身一套系统就能服务于用户的情况很少,大多都要请求本系统外的其它系统(这些系统可能是内部的或是外部的),大家互相交互才形成了可以服务于真正用户的互联网功能。

举例:

  1. 联合会员充值活动 ;
  2. 腾讯自选股;
  3. 话费充值,联系话费充值商。

二、需求分析

基于上述背景,合作方公司提出诉求:需要一种健康度系统,(鲲鹏?网络状况延迟数据分析?),识别外部系统的健康度,并根据健康度控制流量。

简单描述:

  1. 办理成功率;
  2. 网络通讯状况等相关功能。

三、实现目标

3.1 简述:

  1. 我们知道某个合作方是不健康的,就生成一条记录,代表他被打入冷宫,我们的系统查到记录就不会让用户访问它。
  2. 完全自动识别健康度是不可靠的(毕竟是机器),我们必须有人工介入的手段,首先我们允许合作方主动通知我们系统不健康(比如在维护升级、在调整东西、服务出问题、不在交易时间内等等),我们得到这个消息就可以做相应的调整(不让用户看到他家产品)

3.2 详述

  1. 正确接收到合作方系统不健康的消息
  2. 系统内部可以操作不健康消息(增加/删除/修改/查询)
  3. 系统自动识别不健康合作方,并生成不健康记录
  4. 系统自动识别健康度再次达标的合作方,并删除不健康记录

四、系统设计重点

性能、可用性、安全

4.1. 性能:为了速度考虑,信息redis存储,直接查询

  1. 获取合作方提供的健康度信息(不可能每个用户请求都去请求合作方系统)
  2. 判断健康度需要的数据的获取(包括是否连通、成功率、平均耗时、配置等)
  3. 健康状态的判断和灰度逻辑(不可能每个用户请求来现场算是否健康)
  4. 健康状态信息缓存(存redis加快读取速度)

4.2. 可用性: 旁路系统:超时、正确性判定;策略说明如下:

  1. 某些降级策略,如健康度功能不可用时,根据配置的默认顺序来推荐合作方。
  2. 可配置超时时间,按时没运行完也要返回。

4.3. 可用性:我们要保证误判尽量的少,保证最大的正确性。

  1. 合理的判定不健康算法、平滑的过渡方式。
  2. 判断健康的所有指标都可配置,实现精细化运行,根据具体合作方的实际情况配置。

4.4. 安全性:签名认证

  1. 外部交互时: 签名+加密
  2. 内部存储时: 签名

签名和加密,他们的作用是不同的,两者是有区别的。

签名主要功能是防篡改,是无限集合(真实内容)向有限集合(签名)的映射,根据签名是无法还原内容的,接收方收到内容后,按约定的算法和密钥算出签名,和收到的签名一样就是没被篡改。

加密主要功能是防泄漏,是无线集合向无限集合的映射,因为陌生人即使拿到了整个消息,依旧看不懂写的什么,而接收方解密拿到明文可以进行处理。

五、方案设计概述

5.1. 先把合作方和本系统内部的人为干预手段做好,并且搭起基本架构,开始对外提供服务(即,其他服务可查询合作方是否健康)

5.2. 我们再把自动判定健康的数据获取、判定健康、根据健康度控制流量等功能补齐。

eg:某合作方不健康的一条记录,称为“公告”,(合作方)发公告告诉所有关心的模块:我不健康了。

六、手动架构设计

6.1 整体架构设计

6.1.1. DB设计

  1. auto_increment
  2. 供应商id
  3. 公告id
  4. 公告创建时间
  5. 公告更新时间
  6. 操作用户id
  7. 公告开始时间
  8. 公告结束时间
  9. 类型 0:运营商 1:后台 2:自动
  10. 状态 0:无效 1:生效

6.1.2. Ckv存储结构

//不健康信息
//供应商公告key
    key: 
        {"ID":"xxservice_gddianxin"}//前缀+供应商id 
    //Boss后台配置的公告key
    key: 
        {"ID":" xxservice_gddianxin_boss"}//前缀+供应商id+后缀
    value: 
        [   
            {   
                "":"gddianxin", //供应商id 
                "ID":"123123123",  //记录序列id 
                "begin":"2020-7-2 00:00:00",  //开始时间 
                "end":"2020-7-3 00:00:00",  //结束时间 
                "eff":true   //是否生效,部分供应商可能存在取消的情况 
            }
        ]  
    //公告开关
    key: 
        //前缀+供应商id+后缀
        {"ID":"xxservice_gddianxin_flag "} 
    value:
        1(2)//1:打开,2:关闭

6.1.3. 协议设计

6.1.3.1. 合作方交互的接口:

<?xml version="1.0" encoding="UTF-8"?>
<req>
<timestamp>1514736000</timestamp>
<signmsg>XXX</signmsg>
<channel>zhifubao</channel>
</req>
<?xml version="1.0" encoding="UTF-8"?>
<rtn>
  <code>0</code>
  <msg>同步成功</msg>
  <channel>0</channel>
  <upgradeInfo>
    <item>
      <upgradeID> UC-051-20200702-96038</upgradeID>
      <upgradeContent>系统故障</upgradeContent >
      <beginTime>2020-7-2 00:00:00</beginTime>
      <endTime >2020-7-3 00:00:00</endTime>
      <effective>true</effective>
    </item>
    <item>
      <upgradeID> UC-051-20200703-96000</upgradeID>
      <upgradeContent>系统升级</upgradeContent >
      <beginTime>2020-7-3 00:00:00</beginTime>
      <endTime >2020-7-4 00:00:00</endTime>
      <effective>true</effective>
    </item>
  </upgradeInfo>
</rtn>

说明 :

  1. Code是返回码,upgradeInfo是公告列表,含有多个公告主体。
  2. 公告主体含有升级序列id、升级内容、开始时间、结束时间、生效标志等字段。

注意:如某公告被取消,不应在运营商返回的报文中直接消失,而是应将effective置为false


sha256_HMAC作为签名的算法,案例如下:

  1. 假若传入如下参数:bank_type=WX;fee_type=1,body=XXX;
  2. 按照参数key值进行字典排序(按照字段名的ASCII 码从小到大排序),并且使用”&”作为分隔符,把参数串成字符串。bank_type=WX&body=XXX&fee_type=1;
  3. 用双方约好的密钥secret_key,对组装的字符串进行加密signmsg=sha256_HMAC_func(secret_key , bank_type=WX&body=XXX&fee_type=1)。

其它协议如:我方服务的查询接口、定时任务接口、合作方主动推送接口,


版权声明:本文为CSDN博主「兔老大RabbitMQ」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:blog.csdn.net/hebtu666/ar…


    1. 架构设计
      1. 基于性能考虑,我们需要读写分离,读操作直接读redis,节省时间。
      2. 基于可用性考虑,我们的定时任务链路和查询都需要层层注意。
      3. 基于安全考虑(信息的安全和服务本身的安全),我们的外部交互协议和运营后台很重要。

6.2 策略说明:

图示处理概要

  1. 定时任务负责定时触发查询;
  2. 运营商接入服务负责调取运营商接口:向上屏蔽运营商接口的不一致性,对内提供标准接口;
  3. 接入外部接口 ,方便做安全的校验;
  4. 公告服务提供核心的查询和写入功能。

根据上述概要,创建三条链路策略:

针对redis实现,性能方面不需要考虑。

定时任务请求获取公告接口。部署在多台脚本机,如果其中一台出现问题,其它机器依然正常工作。万一真的都挂了,就要触发监控和报警,通过微信或电话直接提示负责人,尽快解决问题。

定时任务负责定时触发查询,运营商接入服务负责调取运营商接口,向上屏蔽运营商接口的不一致性,对内提供标准接口。同时方便做一些安全的校验。

公告服务提供核心的查询和写入功能。

6.3 三条链路的策略:

性能:redis;

6.3.1 定时任务链路:

  1. 定时任务请求获取公告接口。部署在多台脚本机,如果其中一台出现问题,其它机器依然正常工作。万一真的都挂了,就要触发监控和报警,通过微信或电话直接提示负责人,尽快解决问题。
  2. 链路往下走,获取公告接口,负责调用运营商接入服务获取信息,并写入redis。
  3. 运营商接入服务,负责调取运营商接口,向上按标准参数返回。由于查询的无状态,可以多机部署,某台机器挂了可以自动切量。
  4. 各模块有自己的机制保证可用性,如果确实整条链路失效了,公告信息就会暂停更新,不会造成更坏的影响。

6.3.2 查询主链路

  1. 和其他服务交互部分,请求查询公告接口。如果请求异常,会有降级策略:返回系统未维护。另外由于查询是无状态的,多机部署(采用类cl5的策略)保证可用性。
  2. 链路往下走,查询公告接口,它会查询公告信息redis,然后返回结果。这里对查询结果的各种情况的处理就非常关键。
  3. 对于明确成功的结果,就正常返回。对于超时、明确失败、未知情况,都会有降级策略,返回运营商未维护。
  4. 对于超时情况,设置了超时时间为50ms,保证主链路不会耗时过长。

6.3.3 运营后台链路:

  1. 加入了人工干预 系统故障时有人为干涉的兜底策略。
  2. 除了redis其他地方都是无状态的,所以可以多机部署,任何机器出现问题,都会有其他机器保证可用。
  3. 对于redis,有查询降级策略和设置超时时间,即使挂了也不影响主链路。

七、自动部署设计

7.1 异步操作

实现了人工干预手段和公告服务的基本框架,接下来我们完善自动健康度的功能。

如何判定不健康:读取成功率、耗时、探测等数据 考虑到不能因为新系统需要的操作就影响老流程 ,必须做成异步的,譬如:1. 其他程序写redis;2. rabbitmq/kafka,让其他服务放一个消息在消息队列里

方法1和方法2中选择方法1(毕竟一个redis物尽其用,没必要引入消息队列

7.2 不健康判定

探测、多维度检测实时成功率、耗时进行判断。

if 探测失败次数高于阈值:
        挂起公告
if 请求量大于阈值 and (成功率低于某阈值 or 耗时高于某阈值):
        挂起公告。

八、总结

image.png

.