处理意外故障是最难解决的问题之一,特别是在分布式系统中。开发人员编写的大部分代码都涉及异常处理,而这也是测试中花费最多时间的地方。这个问题比编写处理失败的代码更复杂。当运行微服务的机器出现故障时会发生什么情况?您不仅需要检测此微服务故障(这本身就是一个难题),而且还需要一些东西来重新启动您的微服务。
微服务需要对故障具有弹性,并且能够经常在另一台计算机上重新启动以获得可用性。这种弹性还可以归结为代表微服务保存的状态,微服务可以从中恢复此状态,以及微服务是否可以成功重新启动。换句话说,计算能力需要有弹性(进程可以随时重新启动)以及状态或数据的弹性(没有数据丢失,数据保持一致)。
在其他情况下,如在应用程序升级过程中发生故障时,弹性问题会变得更加复杂。使用部署系统的微服务需要确定它是可以继续前进到较新版本,还是可以回滚到以前的版本以保持一致的状态。需要考虑的问题包括是否有足够的机器可以继续前进,以及如何恢复以前版本的微服务。这需要微服务发出运行状况信息,以便整个应用程序和编排器可以做出这些决定。
此外,弹性还与基于云的系统的行为方式有关。如前所述,基于云的系统必须接受失败,并且必须尝试从失败中自动恢复。例如,在网络或容器故障的情况下,客户端应用程序或客户端服务必须具有重试发送消息或重试请求的策略,因为在许多情况下,云中的故障是部分的。本指南中的“实现弹性应用程序”一节介绍了如何处理部分故障。它通过使用诸如Polly之类的库来描述诸如指数退避重试或.NET Core中的断路器模式之类的技术,Polly提供了处理此主题的各种策略。
微服务中的健康管理与诊断
这看起来很明显,而且常常被忽略,但是微服务必须报告其健康状况和诊断。否则,从操作的角度看就没有什么洞察力了。跨一组独立服务关联诊断事件,并处理机器时钟偏差以了解事件顺序,这是一项挑战。正如您通过商定的协议和数据格式与微服务交互一样,需要标准化如何记录最终在事件存储中用于查询和查看的运行状况和诊断事件。在微服务方法中,关键是不同的团队在单一的日志格式上达成一致。需要有一种一致的方法来查看应用程序中的诊断事件。
健康检查
健康与诊断不同。运行状况是指微服务报告其当前状态以采取适当的操作。一个很好的例子是使用升级和部署机制来维护可用性。尽管由于进程崩溃或计算机重新启动,服务当前可能不正常,但该服务可能仍在运行。最不需要的是通过执行升级使情况变得更糟。最好的方法是先做一次调查,或者留出时间让微服务恢复。微服务中的健康事件可以帮助我们做出明智的决策,实际上,有助于创建自愈服务。
在本指南的“在ASP.NET核心服务中实现运行状况检查”部分中,我们将解释如何在您的微服务中使用新的ASP.NET运行状况检查库,以便它们可以向监视服务报告其状态以采取适当的操作。
您还可以选择使用一个优秀的开源库Beat Pulse,它可以在GitHub上作为NuGet包提供。此库还执行运行状况检查,但有一个转折点,它处理两种类型的检查:
- 活动性:检查微服务是否活动,即它是否能够接受请求和响应。
- 就绪性:检查微服务的依赖项(数据库、队列服务等)本身是否就绪,以便微服务可以执行它应该执行的操作。
使用诊断和记录事件流
日志提供有关应用程序或服务如何运行的信息,包括异常、警告和简单的信息消息。通常,每个日志都是一种文本格式,每个事件有一行,但异常也经常显示跨多行的堆栈跟踪。
在基于单片服务器的应用程序中,您可以简单地将日志写入磁盘上的文件(日志文件),然后使用任何工具对其进行分析。由于应用程序的执行仅限于固定服务器或VM,因此分析事件流通常不太复杂。然而,在一个分布式应用程序中,多个服务在一个编排器集群的多个节点上执行,能够关联分布式事件是一个挑战。
基于微服务的应用程序不应试图单独存储事件或日志文件的输出流,甚至不应尝试管理事件到中心位置的路由。它应该是透明的,这意味着每个进程只需将其事件流写入一个标准输出,该输出下面将由运行它的执行环境基础设施收集。这些事件流路由器的一个例子是Microsoft.Diagnostic.EventFlow,它从多个源收集事件流并将其发布到输出系统。这些可以包括开发环境或云系统(如Azure Monitor和Azure Diagnostics)的简单标准输出。还有很好的第三方日志分析平台和工具,可以搜索、警报、报告和监视日志,甚至是实时的,比如Splunk。
管理运行状况和诊断信息的编排器
创建基于微服务的应用程序时,需要处理复杂性。当然,一个microservice很容易处理,但是几十到几百个microservice类型和数千个microservice实例是一个复杂的问题。这不仅仅是为了构建您的微服务体系结构,您还需要高可用性、可寻址性、可恢复性、运行状况和诊断功能,如果您想要有一个稳定和内聚的系统。
图22 微服务平台是应用程序健康管理的基础
图22所示的复杂问题很难自己解决。开发团队应该专注于用基于微服务的方法解决业务问题和构建定制应用程序。他们不应该专注于解决复杂的基础设施问题;如果他们这样做了,任何基于微服务的应用程序的成本都将是巨大的。因此,有一些面向微服务的平台(称为编排器或微服务集群)试图解决构建和运行服务以及高效使用基础设施资源的难题。这减少了构建使用微服务方法的应用程序的复杂性。
不同的编排器听起来可能类似,但它们提供的诊断和运行状况检查在功能和成熟度方面有所不同,有时取决于操作系统平台,如下一节所述。
对于基于Spring Cloud和Kubernets的微服务平台,我们会在后续的章节详细介绍。