微服务依赖管理的陷阱与模式( 三 )


微服务依赖管理的陷阱与模式
文章图片
图3:流量增长的意外影响
在Happytails中推出的特性带来的10%的客户增长与10%的数据库流量增长相一致 。 然而 , 在分析日志后工程团队发现 , 在Furland推出该特性后 , 即使没有一个新用户注册 , 数据库的流量也增长了60% 。 回滚后 , 急于在午休时间看到猫猫照片的不满客户们开了几张客户支持票 。 工程师们总算了解到 , Furland的客户实际上多为爱猫人士 , 当只有狗狗图片能看时 , 他们没什么兴趣与PetPic互动 。
要点
上面的场景告诉我们 , 猫图片特性在吸引Furland的现有客户方面取得了巨大成功 , 但新特性的部署策略完全没能预料到会取得如此大的成功 。 这里的一个重要教训是 , 每种产品都会经历不同类型的增长过程 。 正如我们在这个场景中看到的 , 客户数量的增长与现有客户参与度的增长是不一样的——不同类型的增长并不总是相互关联 。 处理用户请求所需的硬件资源可能因用户行为而异 , 用户行为也可能因许多因素(包括地理区域)而异 。
在准备在不同地区推出产品时 , 最好在所有地区进行特性实验 , 以更全面地了解新特性将如何影响用户行为(以及资源?利用率) 。 此外 , 每当新发布需要额外的硬件资源时 , 明智的做法是让后端所有者有更多时间来动手分配这些资源 。 分配新机器需要采购订单、运输过程和硬件的物理安装过程 。 发布策略需要考虑到这部分额外时间 。
场景二:故障隔离
从架构的角度来看 , 我们刚刚研究的这个场景涉及了一项在运行中成为单点故障的全局服务 , 以及一次导致两个区域中断的本地部署 。 在单体应用的世界中 , 跨组件隔离故障是非常困难 , 甚至无法做到的 。 这种困难的主要原因是所有逻辑组件共存于同一个二进制文件中 , 因此它们也会处于同一个执行环境中 。 使用微服务的一个巨大优势是我们可以允许独立的逻辑组件孤立地发生故障 , 防止故障在整个系统中广泛传播并危及其他组件 。 分析服务如何共同失败的设计过程通常称为故障隔离 。
在我们的示例中 , PetPic独立部署在两个不同的区域:Happytails和Furland 。 但是 , 这些区域的性能表现与为这两个区域提供服务的全局数据库的性能密切相关 。 正如我们目前所观察到的 , Happytails和Furland的客户有着截然不同的兴趣 , 因此很难调整数据库来高效地为这两个地区提供服务 。 Furland客户访问数据库方式的变化可能让Happytail用户遇到糟糕的用户体验 , 反之亦然 。
有一些方法可以避免此类问题 , 例如使用有界本地缓存 , 如图4所示 。 本地缓存可以带来增强的用户体验 , 因为它还可以减少响应延迟和数据库资源使用 。 缓存大小可以适应本地流量而不是全局利用率 。 它还可以在后端中断的情况下提供保存的数据 , 从而实现服务的优雅降级 。
缓存也可能会带来特定于应用程序或业务需求的问题——例如你有很高的数据新鲜度或扩展需求时 。 常见问题包括由于资源限制和查询各种缓存时的一致性导致缓存延迟缓慢增加 。 此外 , 服务不应该依赖缓存的内容来提供服务 。
微服务依赖管理的陷阱与模式
文章图片
图4:使用有界本地缓存进行故障隔离
产品架构中的其他组件呢?对所有内容都使用缓存是否合理?你能否将在云中运行的服务隔离到特定区域?这两个问题的答案都是肯定的 , 如果可以 , 你应该实施这些策略 。 在云中运行服务并不能避免它成为全局中断的根源 。 运行在不同云区域的服务仍然可以作为全局服务运行 , 因此可以成为单点故障来源 。 将服务隔离到故障域是一种架构决策 , 并不能仅由运行服务的基础架构来保证 。