01.2分布式系统的复杂性

分类: 从单体到微服务

分布式系统的复杂性

本节将学习:服务间调用的复杂性、故障定位的困难、性能优化的挑战。这些问题在单体架构中可能很简单,但在分布式系统中就变得非常复杂。

服务间调用的复杂性

在单体架构中,所有的模块都在同一个进程中,调用就是函数调用,非常快,非常简单。

但是在微服务架构中,服务间调用就变得复杂了。为什么呢?

第一个问题是调用链深度增加。

一个用户请求,从前端到后端,可能要经过 API Gateway、User Service、Product Service、Order Service、Payment Service,每个服务可能还要调用数据库、缓存、消息队列。一个请求可能经过 10+ 个服务。

这些服务间还有复杂的依赖关系。User Service 依赖数据库,Product Service 依赖缓存和数据库,Order Service 依赖多个服务。这个依赖关系图会变得非常复杂,难以理解。

第二个问题是网络延迟累积。

在单体架构中,模块间调用是进程内的,几乎没延迟。但是在分布式系统中,每个服务调用都有网络延迟。例如,每个服务调用延迟 10ms,10 个服务就是 100ms。如果某个服务延迟更高,整体响应就会变得很慢。而且,很难知道具体是哪个服务慢。

第三个问题是超时和重试。

服务调用可能会超时。网络可能不稳定,服务可能暂时不可用。这时候就需要重试机制。但是重试可能会造成重复请求,例如,一个订单可能被创建两次,这就带来了新的问题。

第四个问题是服务发现和负载均衡。

在分布式系统中,服务可能有很多实例。如何找到这些服务?如何分配负载?这就需要服务发现机制和负载均衡。配置管理就变得非常复杂。

这就是分布式系统带来的复杂性。

故障定位的困难

在单体架构中,如果出了问题,可能只需要查看一个应用的日志,问题相对简单。

但是在分布式系统中,故障定位就变得非常困难。为什么呢?

第一个问题是问题可能发生在任何环节。

用户投诉说订单创建失败,问题可能在哪里呢?可能是前端有问题,可能是后端 API 有问题,可能是数据库有问题,可能是网络有问题。任何服务都可能出问题,而且问题可能涉及多个服务。

例如,如果 User Service 调用超时,可能是因为 User Service 本身慢,也可能是因为数据库慢,也可能是因为网络慢。很难知道到底是哪里出了问题。

第二个问题是调试信息分散。

每个服务都有自己的日志。需要登录多个服务器,查看多个日志文件,手动拼凑出问题的图景。这个过程非常耗时,而且容易出错。

而且,不同服务的日志格式可能不统一。有些服务用 JSON 格式,有些服务用文本格式。很难统一处理这些日志。

第三个问题是时间同步问题。

不同服务器的时钟可能不同步。看到的日志时间戳可能不准确。这就难以确定事件的先后顺序,难以关联相关事件。

第四个问题是上下文信息丢失。

请求在各个服务间传递,上下文信息可能丢失。例如,用户 ID、订单 ID、Trace ID 这些信息,如果不在每个服务间传递,就会丢失。就难以追踪完整的请求路径。

这就是为什么在分布式系统中,故障定位这么困难。

性能优化的挑战

在单体架构中,可以直接看到代码的执行路径。知道哪个函数慢,可以直接优化。

但是在分布式系统中,性能优化就变得非常困难。为什么呢?

第一个挑战是无法直观看到完整调用链。

不知道请求经过了哪些服务,不知道每个服务耗时多少,不知道哪个服务是瓶颈。就像盲人摸象一样,只能看到一部分,看不到全貌。

例如,用户投诉说 API 响应慢,响应时间是 2 秒。但是不知道这 2 秒花在哪里了。

是前端渲染慢?是 API Gateway 慢?是某个服务慢?是数据库查询慢?不知道。

第二个挑战是瓶颈点难以识别。

性能问题可能出现在任何服务。需要分析大量的性能数据,从 Metrics、Traces、Logs 中找出问题。这个过程非常耗时,而且容易出错。

而且,即使找到了问题,也难以确定优化方向。例如,发现数据库查询慢,但是不知道是查询语句的问题,还是索引的问题,还是数据量的问题。

第三个挑战是优化效果难以量化。

不知道优化前的性能基线,不知道优化后的性能提升是多少。就难以证明优化的价值,难以说服老板投入资源去优化。

这就是为什么在分布式系统中,性能优化这么困难。

本节小结

在本节中,我们学习了分布式系统带来的三个主要复杂性:

第一个是服务间调用的复杂性。 调用链深度增加,网络延迟累积,超时和重试,服务发现和负载均衡。这些问题在单体架构中不存在,但在分布式系统中就变得非常复杂。

第二个是故障定位的困难。 问题可能发生在任何环节,调试信息分散,时间同步问题,上下文信息丢失。传统的方法很难快速定位问题。

第三个是性能优化的挑战。 无法直观看到完整调用链,瓶颈点难以识别,优化效果难以量化。优化变得盲目,效果不明显。

这些复杂性是分布式系统固有的,无法避免。但是,可以通过可观察性来解决这些问题。

在下一节,我们将看看可观察性如何解决这些复杂性,以及它带来的实际价值。