微服务设计模式
1. Database per Service (每个服务一个数据库)
- 目标/目的:
- 实现微服务之间的松耦合。
- 增强服务的独立性、可伸缩性和数据封装。
- 关键概念/工作方式:
- 每个微服务管理自己的私有数据库。
- 数据库只能由拥有该服务的服务访问。
- 强制执行清晰的边界并促进单一职责原则。
- 数据隔离: 减少服务之间的依赖。
- 技术灵活性: 服务可以使用适合其特定需求的不同数据库技术 (例如 MongoDB, DynamoDB, Azure Cosmos DB, Google Cloud Data Store)。
- 独立伸缩: 数据库可以根据每个服务的要求独立伸缩。
- 简化开发: 开发者可以专注于单个服务及其数据模型。
- 数据访问仅通过服务的 API 进行,维护了强大的封装性。
- 挑战/常见错误:
- 数据重复: 可能导致一致性问题。
- 复杂的跨服务查询: 可能需要 API 组合等额外模式。
- 事务管理: 在没有分布式事务的情况下,跨服务确保数据一致性具有挑战性。
- 操作复杂性增加: 管理多个数据库比管理单个共享数据库更具挑战性。
- 过度使用: 不必要地应用于小型服务或紧密耦合的领域会增加复杂性。
- 忽略数据迁移: 在拆分单体数据库时未能规划数据迁移会产生问题。
- 忽略最终一致性: 未设计系统来处理服务之间的最终一致性。
- 应用示例:
- 在将单体电子商务平台 adapting 为微服务架构后应用此模式。
- 每个服务拥有特定表,例如产品服务拥有产品和分类表,库存服务拥有库存和位置表等。
- 通过将数据库模式拆分为更小的、由每个服务独立管理的专用数据库来实现。
- 前提条件:
- 对业务流程和数据有扎实的理解。
- 定义清晰的微服务边界。
- 实施数据治理计划。
2. API Gateway (API 网关)
- 目标/目的:
- 作为客户端请求的单一入口点。
- 通过提供统一接口简化客户端代码。
- 处理跨领域关注点,如认证、日志记录和速率限制。
- 聚合来自多个微服务的响应。
- 提供协议转换和 API 版本控制。
- 关键概念/工作方式:
- 充当反向代理,拦截所有来自客户端的传入 API 调用。
- 将请求路由到适当的微服务。
- 聚合响应并返回给客户端。
- 可以执行额外功能,如认证和授权、请求和响应转换、缓存、监控和分析、速率限制和节流。
- 挑战/常见错误:
- 性能瓶颈: 如果设计不当,可能成为单点故障和性能瓶颈。
- 过度复杂: 添加过多业务逻辑会使其难以维护和伸缩。
- 缺乏版本控制: 未实现适当的 API 版本控制会导致客户端出现破坏性变更。
- 监控不足: 未实现全面的监控和告警会使问题排查困难。
- 安全配置错误: 错误实现认证和授权会导致安全漏洞。
- 紧密耦合: 与底层微服务设计得过于紧密会降低灵活性。
- 应用示例:
- 应用于电子商务解决方案。
- 拦截来自客户端的传入 API 调用,路由请求,并在聚合响应前处理认证、密钥管理和 HTTP/协议转换。
- 实现选项:
- AWS API Gateway。
- Azure API Management。
- Google Cloud Endpoints 和 Apigee Edge。
3. Event Driven Architecture (EDA - 事件驱动架构)
- 目标/目的:
- 实现松耦合、可伸缩和响应迅速的系统,能够实时响应变化。
- 通过允许组件异步通信改进系统灵活性、可伸缩性和容错性。
- 关键概念/工作方式:
- 基于产生、检测、消费和响应事件的思想。
- 事件表示系统中的重要状态变化或发生。
- 事件生产者在发生重要事件时生成事件。
- 事件通过事件通道或消息代理传输。
- 事件消费者订阅相关事件并做出相应反应。
- 促进解耦系统,组件无需了解彼此的存在。
- 挑战/常见错误:
- 管理和版本化事件模式会变得复杂。
- 通常依赖最终一致性,这在需要即时一致性的用例中可能具有挑战性。
- 确保事件的正确顺序,尤其是在分布式系统中。
- 过度使用事件: 并非所有交互都需要是事件驱动的,不必要地增加复杂性。
- 未建立标准事件格式,导致集成困难。
- 忽略持久化重要事件,可能导致关键数据丢失和系统不一致。
- 未实现适当的错误处理。
- 未考虑在分布式系统中调试问题的能力。
- 应用示例:
- 应用于电子商务解决方案,将服务与消息代理连接。
- 例如,用户下单时,购物车服务发送通知给消息代理,产品服务订阅此通知并响应,然后购物车服务确认数量并创建订单。
- 实现选项:
- AWS: Amazon EventBridge, Amazon Simple Notification Service (SNS), Simple Queue Service (SQS)。
- Google Cloud: Cloud Pub/Sub, Cloud Functions。
- Azure: Azure Event Grid, Azure Service Bus, Azure Functions。
4. Service Registry and Discovery (服务注册与发现)
- 目标/目的:
- 解决在分布式系统中动态定位和通信服务的问题。
- 维护可用服务实例的最新目录。
- 实现自动化服务注册。
- 促进动态伸缩和负载均衡。
- 提高系统弹性和容错性。
- 关键概念/工作方式:
- 包含两个主要组件:
- Service Registry (服务注册中心): 一个存储可用服务实例信息 (包括网络位置) 的数据库。
- Service Discovery (服务发现): 服务查找其他服务以进行交互的机制。
- 服务注册:
- 自注册 (Self-registration): 每个微服务在启动时注册自己,关闭时注销。
- 第三方注册 (Third-party): 注册器 (registar) 负责监控微服务的健康状况,并根据其健康状态注册或注销。
- 服务发现:
- 客户端发现 (Client-side Discovery): 每个微服务查询服务注册中心以检索其他服务所需的信息。
- 服务器端发现 (Server-side Discovery): 依赖于代理来协助微服务之间的交互,代理负责路由请求。
- 包含两个主要组件:
- 挑战/常见错误:
- 确保注册中心始终最新,限制临时不一致,避免将流量导向不可用实例。
- 考虑可能的性能开销: 频繁查询注册中心可能影响性能,应实施缓存机制。
- 注册中心本身可能成为瓶颈和单点故障: 必须为注册中心实现高可用性和容错性。
- 安全: 未能保护服务注册中心会暴露关于基础设施的敏感信息。
- 忽视健康检查: 未在每个微服务中实现健壮的健康检查会导致流量被路由到不健康实例。
- 未能实现适当的负载均衡策略,导致流量分布不均。
- 应用示例:
- 在电子商务解决方案中应用。
- API Gateway 知道如何发送登录请求到 Identity and Access Management (IAM) 微服务,就是因为它利用了服务注册与发现。
- 使用第三方方法:微服务启动时,注册器检测它们并更新注册中心。
5. Circuit Breaker (熔断器)
- 目标/目的:
- 防止分布式系统中的级联故障。
- 提高系统弹性和容错性。
- 减少服务故障对整个系统的影响。
- 实现快速故障检测和恢复。
- 关键概念/工作方式:
- 像电气断路器一样工作,监控服务之间的请求流。
- 具有三种状态:
- Closed (关闭): 正常运行状态,请求通过。
- Open (打开): 检测到故障时,请求立即被拒绝。
- Half Open (半打开): 测试服务是否已从先前的故障中恢复。
- 当服务重复失败时,熔断器会跳闸到 Open 状态,阻止进一步的请求。
- 经过定义的超时后,切换到 Half Open 状态以测试服务是否已恢复。
- 如果测试成功,则切换回 Closed;如果失败,则返回 Open 状态。
- 挑战/常见错误:
- 设置故障阈值过低或过高,可能导致过早跳闸或延迟响应故障。
- 未能设置适当的超时。
- 缺乏监控: 未实现适当的监控和告警会使问题难以发现。
- 忽略部分故障: 只关注完全服务故障而忽略性能下降的情况。
- 过度依赖熔断器: 不应将其作为唯一的容错解决方案,应是综合弹性策略的一部分。
- 未能充分测试熔断器行为。
- 应用示例:
- 应用于电子商务解决方案,特别是保护产品服务不被库存服务调用失败影响。
- 描述了库存服务调用产品服务失败,熔断器跳闸,经过指数退避和抖动随机化重试,最终产品服务恢复,熔断器切换回 Closed 的场景。
- 实施时的关键问题:
- 何时应该跳闸?
- 在一定时期内,需要考虑多少次失败请求来做决定?
- 如何量化失败?
- 在将请求视为失败之前,产品服务的预期响应时间或 SLA 是多少?
- 熔断器何时可以再次关闭?
- 熔断器跳闸后多久应该再次尝试?
- 应该给产品服务多长时间恢复?
- 这个模式理念简单,但需要仔细思考如何防止完全系统故障。
大家对这个内容有兴趣的可以看下面的视频。