0%

微服务实践

服务拆分

实践微服务的第一步便是服务拆分, 这也是关键的一步, 按照微服务风格的要求, 首要考虑的是按业务拆分, 这就要求架构师, 先分析业务需求, 做好业务边界, 然后再按照业务模块对系统进行拆分, 一般来说, 拆分需要考虑以下几点

  • 独立性: 拆分出来的服务, 应该是独立的, 它可以独立运行, 支撑某一块业务, 是一个独立的产品, 应该具备高内聚和低耦合的特点, 同时它会保留一些明确的接口, 提供给第三方进行服务调用
  • 明确服务粒度: 服务是根据业务的需要进行划分的, 但是有时候需要考虑粒度, 例如, 用户服务按照公司业务, 需要十分精细化地划分为企业用户和个人用户, 而企业用户十分复杂, 这个时候就可以考虑将用户服务, 拆分为企业用户服务和个人用户服务了, 当然, 如果两者区别不大, 业务不多, 也可以不进行拆分, 这些都需要根据业务数据的大小, 复杂度和边界 (是否清晰) 来决定
  • 团队分配: 微服务的风格要求每一个服务是一个独立的产品, 要有独立的团队进行开发, 运维和部署, 而实际上, 这样成本会十分高, 有时候, 由于人员投入不足, 一个团队维护多个业务微服务系统也是常见的, 这时就需要考虑业务和团队的协作问题了, 需要进行合理的分工和业务分配
  • 演进型: 微服务的拆分不是一成不变的, 它会随着时间的变化而变化, 例如, 刚开始, 用户业务数据并不多, 业务也相对单一, 这个时候有一个用户服务就可以了, 但是后续随着业务的深化, 用户数据会急剧膨胀, 在业务划分上也会更精细化, 会将用户分为高级用户和普通用户管理, 这时就可以考虑将原有的用户服务拆分为普通用户服务和高级用户服务两个服务了, 所以在设计的时候, 需要考虑未来可能的细化方向
  • 避免循环依赖和双向依赖: 微服务应该避免循环依赖, 一个业务不能同时由两个系统维护, 必须有清晰的边界, 例如, 很多时候产品和财务是关联的, 有时候财务需要按照产品维度出报表, 这里需要明确的是, 产品表只能在产品服务内维护, 而财务需要产品的信息, 需要有明确的接口和同步时间界限, 以避免财务的内容去维护产品的内容, 造成数据的混乱

微服务的拆分规则并不是平等的, 应该以业务拆分为第一原则, 进行划分, 界定清楚边界, 提供少量的服务接口供外部调用, 同时应该考虑实际的情况, 如需求的细化程度, 数据量, 团队拥有的资源, 未来的预期和硬件情况等, 实施微服务

服务设计

通过服务划分, 可以得到各个单一功能的服务, 在系统的设计过程中, 可以参考以下原则

  • 高可用性: 高可用性是微服务设计的第一原则, 也就是尽可能给予反馈, 任何一个服务都应该至少有 2 个实例, 任何一个实例出现故障, 都可以被微服务系统发现, 并且微服务系统可以通过自我修复排除故障节点, 尽可能保证微服务能够持续稳定地提供给用户服务
  • 伸缩性: 对于快速膨胀, 数据不断增加的服务, 我们可以根据需要增加服务实例, 对于业务减少, 活跃用户减少的服务, 也可以根据需要适当减少服务实例
  • 容错性: 微服务应该具备高容错性, 在一些糟糕的环境下 (如高并发) , 可以通过限流, 熔断和服务降级来保证服务之间的故障不蔓延, 保证各个服务能够尽可能响应用户, 降低服务出现的差错
  • 去中心化: 微服务不推荐遵从服务器, 而是推荐去中心化, 任何一个服务实例都是平等的, 或者按照一定的权重进行分配的
  • 基础设施自动化: 可使用 DevOps 的理念进行开发和测试, 也可使用容器 (如 Docker 等) 简化微服务的部署, 使用这些工具可进一步简化开发, 测试, 部署和运维工作, 使得工作更少, 更加智能
  • 弱一致性: 微服务不推荐使用强一致性, 因为强一致性缓慢且复杂, 弱一致性则相对简单, 在分布式中能够做到简单就相当不易了
  • 性能: 微服务推荐的是使用 REST 风格的请求来暴露服务接口, 让各个服务能够通过服务调用来完成交互, 共同完成业务, 但是 REST 风格缓慢, 在处理高并发场景的时候, 还需要考虑使用其他的技术 (如远程调用) , 以满足性能的需要
  • 可监控: 服务实例都是可以监控的, 出现故障可以及时发现, 并且提示运维人员进行维护

服务架构

  • API 网关: API 网关可以实现路由, 限流和降级的功能, 例如, 我们可以使用介绍过的 Netflix Zuul 或者 Spring Cloud Gateway 进行路由, 也可以使用 Resilience4j 限速器或者 Zuul 插件进行限流, 控制服务的流量
  • 服务和其实例: 服务是根据服务拆分方法得到的一个独立的产品, 它有明确的业务规则, 边界和接口, 服务是由多个实例来完成的, 多个实例可以满足高可用和高性能的需求
  • 服务调用: 各个服务通过服务调用来完成企业的业务, 在一般情况下, 我们可以使用基于 REST 风格的服务调用 (如 Ribbon 和 OpenFeign) , 它具备更高的可读性和独立性, 但是性能不高, 如果需要提升性能的, 还可以考虑远程调用 (RPC) 技术, 但是在一般情况下, 需要考虑使用断路器 (Hystrix 或者 Resilience4j) 对服务调用进行保护, 以避免出现雪崩效应, 导致服务最终失败