01.1、单体架构vs微服务架构
单体架构 vs 微服务架构
在上一章,我们了解了什么是可观察性。本节将深入探讨:为什么在微服务架构中需要可观察性?
本节将从架构演进开始,理解从单体架构到微服务架构的转变,以及这种转变带来的挑战。
架构演进历程
第一阶段:单体架构(Monolith)
在 2000 年代到 2010 年代初期,大多数应用都是单体架构。所有功能集中在一个应用中,使用同一个代码库、同一个数据库。
这种架构的特点:
- 所有功能集中在一个应用中
- 简单的部署和管理:只需要部署一个应用
- 开发速度快:不需要考虑服务间通信
- 适合小规模团队:代码集中,容易理解
第二阶段:微服务架构(Microservices)
从 2010 年代开始,随着业务规模的增长和团队规模的扩大,单体架构逐渐无法满足需求,微服务架构开始流行。
微服务架构的特点:
- 功能拆分为独立的服务:每个服务负责一个业务域
- 每个服务独立部署和扩展:可以根据负载独立扩展
- 技术栈灵活:不同服务可以使用不同的技术栈
- 适合大规模团队:团队可以独立开发和服务
演进的原因:
- 业务规模增长:单体应用无法应对大规模业务
- 团队规模扩大:需要多人协作开发
- 技术栈多样化:不同功能需要不同的技术栈
- 部署和扩展需求:需要独立部署和扩展
这就是架构演进的过程。但这种演进也带来了新的挑战。
单体架构的特点
单体架构的示意图:
所有的功能模块——用户模块、商品模块、订单模块、支付模块——都在一个应用中。它们共享同一个数据库,运行在同一个进程里。
单体架构的优点:
首先是简单。架构简单,容易理解。所有功能都在一个地方,不需要考虑服务间通信、网络延迟等问题。
其次是开发快。不需要考虑服务间通信,开发效率高。开发者可以直接调用函数,而不是调用远程 API。
第三是部署简单。只需要部署一个应用,不需要考虑服务间的依赖关系。
第四是测试容易。所有功能在同一个应用中,可以很容易地进行集成测试。
单体架构的缺点:
首先是扩展困难。所有功能绑定在一起,无法独立扩展。如果只需要扩展订单功能,但必须扩展整个应用。
其次是技术栈固定。所有功能必须使用相同的技术栈。如果想用 Python 开发某个功能,但应用是 Java 的,则不可行。
第三是团队协作困难。多人修改同一个代码库,容易产生冲突。团队规模大了之后,协作成本很高。
第四是故障影响大。一个模块出问题,可能影响整个应用。例如支付模块出问题,可能影响整个系统。
这就是为什么需要微服务架构的原因。
微服务架构的特点
微服务架构的示意图:
功能被拆分为独立的服务——用户服务、商品服务、订单服务。它们各自有独立的代码库、独立的数据库(或共享数据库的不同表)。它们通过 API Gateway 对外提供服务,通过 HTTP 或消息队列通信。
微服务架构的优点:
首先是独立扩展。每个服务可以独立扩展。如果订单服务负载高,可以只扩展订单服务,而不需要扩展整个系统。
其次是技术栈灵活。不同服务可以使用不同的技术栈。用户服务可以用 Java,商品服务可以用 Python,订单服务可以用 Go。每个团队可以选择最适合的技术。
第三是团队协作。团队可以独立开发服务,减少代码冲突。每个团队负责一个服务,协作成本低。
第四是故障隔离。一个服务出问题,不影响其他服务。例如支付服务出问题,其他服务仍然可以正常工作。
微服务架构的缺点:
首先是复杂度高。架构复杂,难以理解。需要理解多个服务之间的关系。
其次是开发慢。需要考虑服务间通信、网络延迟、服务发现等问题,开发效率可能降低。
第三是部署复杂。需要管理多个服务,需要处理服务间的依赖关系。
第四是故障排查困难。问题可能涉及多个服务,需要追踪多个服务才能定位问题。
这就是为什么在微服务架构中需要可观察性的原因。
微服务架构带来的挑战
微服务架构带来了四个主要挑战:
第一个挑战:系统复杂性增加
在单体架构中,可能只需要管理一个应用。但在微服务架构中,可能需要管理 10+ 个服务。这些服务之间有复杂的调用关系。一个用户请求可能经过:
- API Gateway → User Service → Database
- API Gateway → Product Service → Cache → Database
- API Gateway → Order Service → Payment Service → External API
服务间的依赖关系难以理解。一个服务的故障可能影响多个服务。
第二个挑战:故障定位困难
在单体架构中,如果出现问题,只需要在一个应用中查找。但在微服务架构中,问题可能发生在任何服务。例如订单处理失败,可能的原因有:
- User Service 超时?
- Product Service 错误?
- Order Service 异常?
- Payment Service 失败?
需要追踪多个服务才能定位问题。传统的排查方法可能需要登录多个服务器,查看多个日志文件。
第三个挑战:性能优化困难
在单体架构中,可以直接看到代码的执行路径。但在微服务架构中,无法直观看到完整调用链。例如 API 响应慢,瓶颈在哪里?
- 前端渲染慢?
- API Gateway 延迟?
- 某个服务慢?
- 数据库查询慢?
瓶颈点难以识别,优化方向不明确。
第四个挑战:运维管理复杂
在单体架构中,只需要监控一个应用。但在微服务架构中,需要监控多个服务。需要监控:
- 每个服务的 CPU、内存使用率
- 每个服务的错误率
- 每个服务的日志
- 服务间的通信情况
配置管理复杂,日志分散,运维成本高。
这就是微服务架构带来的挑战。可观察性就是为了解决这些挑战。
可观察性如何解决这些挑战
第一个解决方案:应对系统复杂性
可观察性通过 Traces 让开发者看到完整的请求路径。无论一个请求经过多少个服务,都能看到一个完整的 Trace,理解服务间的依赖关系。
传统方法需要查看多个日志文件,手动拼凑调用链。使用可观察性,只需要一个 Trace ID,就能看到完整的链路。效率提升 60-80%。
第二个解决方案:应对故障定位困难
可观察性提供统一的 Dashboard 展示所有服务状态。通过 Trace ID,可以关联 Traces、Metrics、Logs,从问题现象到根因的快速定位。
传统方法可能需要 2-4 小时才能定位问题。使用可观察性,可以在 15-30 分钟内定位问题。效率提升 75-87%。
第三个解决方案:应对性能优化困难
可观察性通过 Traces 显示每个 Span 的耗时,通过 Metrics 显示每个服务的性能指标,通过 Logs 提供详细的执行信息。开发者可以一目了然地看到瓶颈点。
传统方法无法直观看到瓶颈,需要猜测和验证。使用可观察性,能直接看到瓶颈点,优化方向明确。优化效率提升 60-80%。
第四个解决方案:应对运维管理复杂
可观察性提供统一的 Dashboard 展示所有服务,集中化日志管理(如 Loki),自动化告警和通知。不需要登录多个服务器,就能看到所有信息。
传统方法需要登录多个服务器,查看多个日志文件。使用可观察性,只需要一个 Dashboard,就能看到所有信息。运维效率提升 50-70%。
这就是可观察性在微服务架构中的价值。
本节小结
在本节中,我们学习了:
- 架构演进历程:从单体架构到微服务架构
- 单体架构的特点:简单但扩展困难
- 微服务架构的特点:灵活但复杂
- 微服务架构带来的挑战:系统复杂性、故障定位困难、性能优化困难、运维管理复杂
- 可观察性如何解决这些挑战:端到端追踪、统一监控、关联分析
核心观点是:微服务架构带来更高的复杂性,而可观察性就是应对这些复杂性的解决方案。
没有可观察性,微服务架构的复杂性会让开发者寸步难行。有了可观察性,就能驾驭微服务架构的复杂性,发挥微服务架构的优势。
在下一节,我们将深入讨论分布式系统的复杂性:服务间调用的复杂性、故障定位的困难、性能优化的挑战。