一、背景
独自利用自身一套系统就能服务于用户的情况很少,大多都要请求本系统外的其它系统(这些系统可能是内部的或是外部的),大家互相交互才形成了可以服务于真正用户的互联网功能。
举例:
- 联合会员充值活动 ;
- 腾讯自选股;
- 话费充值,联系话费充值商。
二、需求分析
基于上述背景,合作方公司提出诉求:需要一种健康度系统,(鲲鹏?网络状况延迟数据分析?),识别外部系统的健康度,并根据健康度控制流量。
简单描述:
- 办理成功率;
- 网络通讯状况等相关功能。
三、实现目标
3.1 简述:
- 我们知道某个合作方是不健康的,就生成一条记录,代表他被打入冷宫,我们的系统查到记录就不会让用户访问它。
- 完全自动识别健康度是不可靠的(毕竟是机器),我们必须有人工介入的手段,首先我们允许合作方主动通知我们系统不健康(比如在维护升级、在调整东西、服务出问题、不在交易时间内等等),我们得到这个消息就可以做相应的调整(不让用户看到他家产品)
3.2 详述
- 正确接收到合作方系统不健康的消息
- 系统内部可以操作不健康消息(增加/删除/修改/查询)
- 系统自动识别不健康合作方,并生成不健康记录
- 系统自动识别健康度再次达标的合作方,并删除不健康记录
四、系统设计重点
性能、可用性、安全
4.1. 性能:为了速度考虑,信息redis存储,直接查询
- 获取合作方提供的健康度信息(不可能每个用户请求都去请求合作方系统)
- 判断健康度需要的数据的获取(包括是否连通、成功率、平均耗时、配置等)
- 健康状态的判断和灰度逻辑(不可能每个用户请求来现场算是否健康)
- 健康状态信息缓存(存redis加快读取速度)
4.2. 可用性: 旁路系统:超时、正确性判定;策略说明如下:
- 某些降级策略,如健康度功能不可用时,根据配置的默认顺序来推荐合作方。
- 可配置超时时间,按时没运行完也要返回。
4.3. 可用性:我们要保证误判尽量的少,保证最大的正确性。
- 合理的判定不健康算法、平滑的过渡方式。
- 判断健康的所有指标都可配置,实现精细化运行,根据具体合作方的实际情况配置。
4.4. 安全性:签名认证
- 外部交互时: 签名+加密
- 内部存储时: 签名
签名和加密,他们的作用是不同的,两者是有区别的。
签名主要功能是防篡改,是无限集合(真实内容)向有限集合(签名)的映射,根据签名是无法还原内容的,接收方收到内容后,按约定的算法和密钥算出签名,和收到的签名一样就是没被篡改。
加密主要功能是防泄漏,是无线集合向无限集合的映射,因为陌生人即使拿到了整个消息,依旧看不懂写的什么,而接收方解密拿到明文可以进行处理。
五、方案设计概述
5.1. 先把合作方和本系统内部的人为干预手段做好,并且搭起基本架构,开始对外提供服务(即,其他服务可查询合作方是否健康)
5.2. 我们再把自动判定健康的数据获取、判定健康、根据健康度控制流量等功能补齐。
eg:某合作方不健康的一条记录,称为“公告”,(合作方)发公告告诉所有关心的模块:我不健康了。
六、手动架构设计
6.1 整体架构设计
6.1.1. DB设计
- auto_increment
- 供应商id
- 公告id
- 公告创建时间
- 公告更新时间
- 操作用户id
- 公告开始时间
- 公告结束时间
- 类型 0:运营商 1:后台 2:自动
- 状态 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>
说明 :
- Code是返回码,upgradeInfo是公告列表,含有多个公告主体。
- 公告主体含有升级序列id、升级内容、开始时间、结束时间、生效标志等字段。
注意:如某公告被取消,不应在运营商返回的报文中直接消失,而是应将
effective置为false;
sha256_HMAC作为签名的算法,案例如下:
- 假若传入如下参数:bank_type=WX;fee_type=1,body=XXX;
- 按照参数key值进行字典排序(按照字段名的ASCII 码从小到大排序),并且使用”&”作为分隔符,把参数串成字符串。bank_type=WX&body=XXX&fee_type=1;
- 用双方约好的密钥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…
-
- 架构设计
-
-
- 基于性能考虑,我们需要读写分离,读操作直接读redis,节省时间。
- 基于可用性考虑,我们的定时任务链路和查询都需要层层注意。
- 基于安全考虑(信息的安全和服务本身的安全),我们的外部交互协议和运营后台很重要。
-
6.2 策略说明:
图示处理概要:
- 定时任务负责定时触发查询;
- 运营商接入服务负责调取运营商接口:向上屏蔽运营商接口的不一致性,对内提供标准接口;
- 接入外部接口 ,方便做安全的校验;
- 公告服务提供核心的查询和写入功能。
根据上述概要,创建三条链路策略:
针对redis实现,性能方面不需要考虑。
定时任务请求获取公告接口。部署在多台脚本机,如果其中一台出现问题,其它机器依然正常工作。万一真的都挂了,就要触发监控和报警,通过微信或电话直接提示负责人,尽快解决问题。
定时任务负责定时触发查询,运营商接入服务负责调取运营商接口,向上屏蔽运营商接口的不一致性,对内提供标准接口。同时方便做一些安全的校验。
公告服务提供核心的查询和写入功能。
6.3 三条链路的策略:
性能:redis;
6.3.1 定时任务链路:
- 定时任务请求获取公告接口。部署在多台脚本机,如果其中一台出现问题,其它机器依然正常工作。万一真的都挂了,就要触发监控和报警,通过微信或电话直接提示负责人,尽快解决问题。
- 链路往下走,获取公告接口,负责调用运营商接入服务获取信息,并写入redis。
- 运营商接入服务,负责调取运营商接口,向上按标准参数返回。由于查询的无状态,可以多机部署,某台机器挂了可以自动切量。
- 各模块有自己的机制保证可用性,如果确实整条链路失效了,公告信息就会暂停更新,不会造成更坏的影响。
6.3.2 查询主链路
- 和其他服务交互部分,请求查询公告接口。如果请求异常,会有降级策略:返回系统未维护。另外由于查询是无状态的,多机部署(采用类cl5的策略)保证可用性。
- 链路往下走,查询公告接口,它会查询公告信息redis,然后返回结果。这里对查询结果的各种情况的处理就非常关键。
- 对于明确成功的结果,就正常返回。对于超时、明确失败、未知情况,都会有降级策略,返回运营商未维护。
- 对于超时情况,设置了超时时间为50ms,保证主链路不会耗时过长。
6.3.3 运营后台链路:
- 加入了人工干预 系统故障时有人为干涉的兜底策略。
- 除了redis其他地方都是无状态的,所以可以多机部署,任何机器出现问题,都会有其他机器保证可用。
- 对于redis,有查询降级策略和设置超时时间,即使挂了也不影响主链路。
七、自动部署设计
7.1 异步操作
实现了人工干预手段和公告服务的基本框架,接下来我们完善自动健康度的功能。
如何判定不健康:读取成功率、耗时、探测等数据 考虑到不能因为新系统需要的操作就影响老流程 ,必须做成异步的,譬如:1. 其他程序写redis;2. rabbitmq/kafka,让其他服务放一个消息在消息队列里
方法1和方法2中选择方法1(毕竟一个redis物尽其用,没必要引入消息队列
7.2 不健康判定
探测、多维度检测实时成功率、耗时进行判断。
if 探测失败次数高于阈值:
挂起公告
if 请求量大于阈值 and (成功率低于某阈值 or 耗时高于某阈值):
挂起公告。
八、总结
.