兜底策略在微服务系统中的应用

概述

微服务的广泛应用,使得模块间功能划分更加清晰,代码可维护性高。但并不是说微服务的运维成本更低了。假设原先是一个单体服务,我们将它进行微服务化的改造,拆成了多个服务,这时一旦下游服务出现问题,整体服务也会受到影响。

兜底策略是在整体(微服务)系统出现问题时,仍然尽可能去保障服务的可用性(通常以一定数据精度损失作为代价)。

案例

试想我们有一个配置中心服务,它会定期更新线上各服务的配置参数。那么当我们设计服务时,其实是需要考虑到一旦配置中心出现故障,对我们服务的影响。我们可以这么设计:首先提供一个本地配置文件(当然它的参数肯定比较过时了),作为任何异常情况下的兜底。其次将每次从配置中心上拉下来的配置参数,写一份到本地,这样即使后续读取失败,我们也会有一份比较新的配置参数可用。最后我们再开一个线程,实时拉取新的参数,进行更新操作。按照这种方式,将服务从强依赖配置中心,改为了弱依赖。不过需要考虑到这种设计带来的复杂度,如拉取新的配置文件到写入本地磁盘,这一过程是原子操作的。

另一个案例是做路线计算,我们有两套算法v1和v2。v1比较简单,稳定性高,但是不够精确。V2会持续迭代,算法复杂度高。我们可以这么设计自己的系统,将v1策略和v2策略都实现为一个单独的微服务。我们的服务优先调用v2策略,因为它更为精确。但当该服务出现故障时,如返回错误率超过设定阈值,返回latency超过设定阈值等,我们可以切换到v1策略,同时发出报警让人感知。使用这个方案,v1策略实际是v2策略的一个备份,通常我们可以不使用,只是在v2策略无法正常工作时,才会启动使用。这种思路其实和zk选主的思路是一致的,同一时刻只有一个master节点,只有该节点不能正常工作时,其它节点才会替代其工作。然而在大多数情况下,其它节点只是master节点的一个备份而已。

我之前做运营系统时,也使用过兜底策略。新开发的运营系统,需要每天凌晨跑一个job,这个job比较复杂,而且运营活动的一个特点是,都是开发的新的活动,无之前的运维经验。我是这么设计的:首先让它每隔一小时就启动判断一次,如果该任务当天已经完成了,就不再重新启动,否则开始运行当天的job;其次我会假设万一当天所有的job运算失败了,我在配置文件中仍然会配置一个默认参数,这时直接使用该参数进行兜底。这套设计思路使用了两种兜底方案,一是重试,二是默认参数。

使用兜底策略的场景还有很多:如地图上两点间的距离,我们可以通过计算直线距离,乘以一个系数;用户手机的位置信息,我们可以缓存一段时间的坐标值。我们在设计系统时,如果能多想一下该功能是否必须是强依赖的。如果是弱依赖的功能,能否通过兜底方案减少出现问题时的损失,我们服务的稳定性将能进一步提升。

你可能感兴趣的:(技术心得,架构,微服务,运维)