litefish 2018-07-12
随着越来越多企业开始落地微服务架构,Service Mesh和相关的解决方案在社区内的讨论热度开始逐渐上涨。Service Mesh所提倡的“全栈可观察性”、透明安全性、系统弹性等特性令人着迷,但它真的是云原生应用的绝配吗?本文将对Service Mesh何时make sense、何时不那么make sense作出一些思考。
做好微服务架构可以让我们更敏捷
当下来看,产品和服务的“time to market”决定了企业的竞争力,能够对市场和客户需求快速反应的公司想不成功都难。微服务架构为软件敏捷性和整个工作流的“速度”提供了强有力的支持,通过授权不同团队分别处理应用的不同部分,决策是“去中心化”的。
“去中心化”的决策带来了两个关键结果。首先,软件团队可以在架构、发布、测试等方面作出“本地化”的最优决策,不需要依赖全局标准。举个例子,每个团队都有自己的发布工具,而不是单一的标准化应用发布。第二,团队可以更快进行决策,传统模式下韵味、架构等等集中功能之上的阻碍减少了。
微服务架构不是“免费”的——带来了新的失败模式
采用微服务对您的组织、流程和体系结构具有深远的影响。微服务架构本身是一个分布式系统,在基于微服务架构的应用中,业务逻辑分布在通过网络相互通信的多个服务之间,而分布式系统有更多的故障模式(failure mode)。
考虑到这些失败模式,有一个体系结构和过程来防止小的失败变成大的失败是非常重要的。当我们很“快”的时候,失败是不可避免的,例如服务更新时引入了错误,服务在负载下崩溃等等。
随着应用变得越来越复杂,对于失败管理的需求也越来越迫切。当应用由少量微服务组城市,故障还比较容易隔离和排除,但想象数十个、上百个微服务,以及分布在各地的团队,我们的失败管理体系需要与应用一起“伸缩”。
管理失败
我们一般会采取三种失败管理策略:主动测试(proactive testing)、缓解(mitigation)、快速想用(rapid response)。
Service mesh
当服务失败时,会对其上游和下游服务产生影响。通过正确管理服务之间的通信,可以极大地减轻失败服务的影响。这就是Service Mesh的用武之地。
Service Mesh管理服务级别(例如7层代理)通信,提供了强大的原语,可用于所有三种失败管理策略:
动态路由,可用于不同的发布和测试策略,如金丝雀路由、流量阴影或蓝绿部署
弹性,通过诸如断路和速率限制等策略来减轻故障的影响
可观察性,通过收集度量标准,为服务间通信添加context(例如跟踪数据)来提高响应时间
Service Mesh以一种对应用开发人员非常透明的方式添加这些特性。
Service Mesh可以帮助我们更快构建应用吗?
决定Service Mesh对于我们的企业是否有益,首先要思考两个关键问题:
服务拓扑
如果只是单个微服务,Service Mesh的好处是有限的。增量版本也可以通过现有的基础设施(如Kubernetes或API网关)来完成。
然而随着服务拓扑结构越来越复杂,Service Mesh将发挥巨大威力。需要考虑的关键约束是服务调用链的深度。如果您有一个浅层的拓扑结构,您的monolith直接调用了十几种微服务,那么Service Mesh的好处仍然是有限的。当您引入更多的服务到服务的通信时,服务A调用服务B调用服务C,Service Mesh就变得十分重要了。
将您的服务网格集成到您的SDLC中
Service Mesh对于服务是同名的,它是一个丰富的7层网络,微服务不需要任何的代码修改。
然而部署Service Mesh并不会自动加速应用的速率和敏捷性。我们需要将Service Mesh集成到开发过程中。
将实现故障管理策略作为SDLC的一部分
Service Mesh为故障管理提供了强大的原语,接下来我们将讨论各个失败管理策略以及如何应用到SDLC中。
主动测试
微服务应用的测试策略应该尽可能贴近真实情况。考虑到多服务应用的复杂性,当前的测试策略强调在生产中进行测试(或使用生产数据)。
Service Mesh通过控制L7传输到服务的流量来在生产环境中进行测试。例如,服务网格可以将1%的流量路由到服务的v1.1版本, 99%的流量路由到v1.0(金丝雀部署)。这些功能通过声明式路由规则(例如linkerd dtab或Istio路由规则)公开。
Service Mesh不是主动测试的唯一方法。其他补充策略包括使用容器调度器(如Kubernetes)进行滚动更新、可以进行金丝雀部署的API网关或chaos engineering。
有了所有这些策略,谁管理测试工作流的问题就变得很明显了。在Service Mesh中,路由规则可以由管理网格的同一团队集中管理。
缓解
由于各种原因,服务可能会失败:代码错误、资源不足、硬件故障。限制失败服务的爆炸半径对于整个应用程序继续运行(尽管处于降级状态)非常重要。
Service Mesh通过负载平衡、断路器和服务到服务通信的速率限制等弹性模式来减轻故障的影响。例如在重载下的服务可以限制速率,以便仍然处理某些响应,而不会导致整个服务在负载下崩溃。
减轻失败的其他策略包括使用智能RPC库(例如Hystrix)或依赖容器调度程序。像Kubernetes这样的容器调度器支持健康检查、自动扩展和对不响应健康检查的服务的动态路由。
当为给定的服务适当地配置这些缓解策略时,它们是最有效的。例如,不同的服务可以处理不同数量的请求,需要不同的速率限制。如何制定利率限制等政策?Netflix已经实现了一些自动配置算法来设置这些值。其他方法是将这些功能公开给服务作者,他们可以正确配置服务。
可观察性
失败是不可避免的。实现可观察性——跨越监控、警报/可视化、分布式跟踪和日志记录——对于将响应时间最小化到给定的故障是非常重要的。
Service Mesh自动收集关于服务到服务通信的详细指标,包括吞吐量、延迟和可用性的数据。此外,服务网格可以注入必要的headers来支持分布式跟踪。注意,这些headers仍然需要由服务本身传播。