服务框架的可靠性设计与实践
2018-05-11 13:21:01 0 举报
AI智能生成
分布式服务可靠性设计,围绕着日志、建模、容错、意识、习惯展开
作者其他创作
大纲/内容
基本
日志
在出错时,日志中包含尽量多的有用上下文信息
为什么可以这么做?
多打印信息不会是影响性能的主要原因
出错是小概率分支
如果是出错是大概率分支那,打日志以外操作更会成为瓶颈!
便于排错
想想,出了异常又没有调用栈的情况
想想,支持时N次询问,你用的是哪个Dubbo版本?哪个服务方法出错?
减少支持时间,比起开发所用的实现时间,线上和线下的排查/支持要花费很多时间
调用栈,打印异常
不要呑异常
框架自身的版本号
请求信息
Server & Client端的IP
Request信息
服务信息:接口、方法、版本等等
如果是超时
配置的超时时间
本次处理所用的时间
是Server端超时还Client超时?
重试的次数,本次重试的是第几次
……
给出的出错原因描述,要容易理解
尽量在日志信息中给出排错和解决的方法
如:线程池溢出,在异常信息中给出 命令jstack 可以排查线程Hang在什么操作上
明确日志级别的含义
ERROR:系统出错,需要立即处理
WARNING:出错,但可以自行恢复(亚健康),可以不干预
可以定期分析WARNING,了解系统亚健康程度和原因
同一原因不要引起多次重复记录
Provider不可用导致每调一次都相同的ERROR日志
这样做保证日志信息浓度,让排查/监控更有效
异常
不要丢掉Cause异常
Wrapper成上层异常,要提供上层信息
上层异常要加上Message,描述对应的上层语义
记录上层的上下文信息(这一点在日志中也说了)
配置
严格检查,不符合则报警(给出原因和解决方法)
提供覆盖策略
可配置则可编程
方便第三方代码平等/灵活的使用(如框架集成)
方便在运行时修改
建模
明确约定 术语的含义 以及 所在领域
Serialization vs Codec vs Protocol
Serialization:表示序列化,Object到byte[],remoting传输层
Codec:表示RpcInvocation/RpcResult的编码,Rpc层。这个操作包含会使用Serialization写入方法参数。
Protocol: RPC不同协议的抽象,如HTTP协议,原生Hessian
Cluster & Router & LoadBalance & Directory
Cluster: 表示多个Provider集群,Provider列表的外围抽象
Router: 由路由规则,过滤成部分Provider的列表
LoadBalance: 从路由后列表中,选一个调用
Directory: Provider列表,代表Provider列表来源比如ConfigServer的Provider列表Directory
Transport vs Exchange
Transport: 完成OneWay的Send和Receive的Remoting
Exchange:完成Resquest/Response的Remoting。(实现上基于Transport完成)
为什么这么做?
2个术语的字面意思往往比较暧昧
不明确会带交流的困难,进而直接影响设计的清晰性
前期约定的术语的含义和场合,后期接受即可。不用太过于纠结于术语是否十分的到位
贯通使用一个模型,避免转换
URL:贯通表示配置
控制
容错
Fail Fast/Fail Safe/Fail Over
什么时候不容错?
可以Fail-Fast时
开发时,可以发现问题?
不允许的配置值
ERROR日志
启动时,可以发现的问题?
如果没有Provider,(缺省)Consumer启动时报错反馈,并启动失败!
运行时,上层可以Fail-Over?
Provider线程池耗尽,调用失败,Consumer马上收到异常,可以重试其它的Provider
线程池的RejectedExecution策略,使用Aborted
线程池的workQueue设置成SynchronousQueue,不排队任务
下层打ERROR日志,上层打WARNING日志
容错实现复杂,增加出错可能性和排查的难度
区分出 主流程/关键路径
保证主流程/关键路径不受影响
非关键路径 不Break 关键路径,容错掉
监控数据上报失败(Fail Safe)
涉及 下面2个区分
区分出 依赖外部的关键数据。做内存缓存、本地文件缓存
关键数据,即是指没有了系统就挂了
Provider列表
注册中心列表
隔离故障
应用可以临时基于过时的内存缓存数据运行
有本地文件缓存,重启后应用也有过时的缓存数据
要ERROR日志,要报警。不要掩盖了运行时的问题!基于临时数据运行即是故障,即使隔离了!!
区分 可靠操作和不可靠操作
是否会抛出异常或引起状态不一致的操作是不可靠的
分离不可靠操作后,为容错/自我保护/自动恢复/切换等补偿逻辑提供清晰的切入点
保证后续增加的代码时容错逻辑清晰,导致容错处理约定陷入混乱
注意重试逻辑
重试冷却,避免因重试引发雪崩,如指数间隔重试策略,
避免可能所有Client重试的情况(如果可能,添加首次重试 随机延迟)
及早发现不可用的结点并剔除
LoadBalance前,先去掉不可用的Provider,避免之后调用时是不可用的Provider
设置资源上限
容器的上限
Cache元素个数
任务的等待队列大小
根据实际情况,在到达上限后,丢弃老数据或是报错
边界检查
检查空指针
检查容器和数组边界
意识&习惯
不遗漏任何else
向上抛异常,汇报,Fast Fail
忽略掉,Fail safe
要给出上下文 和 不期望这个路径原因
对输入作全集分析,不在处理范围的区间,按上面的方式处理
可靠性的实践与设计
收藏
收藏
0 条评论
下一页