Skip to content
0

微服务

服务拆分

注意

微服务的拆分没有标准,以下也只是给出指导性建议。

微服务拆分粒度的“三个火枪手”原则:一个微服务三个人负责开发。根据团队规模来划分微服务数量,如果业务和团队规模扩大,再将已有的微服务进行拆分。例如:团队初始有6人,那么可以划分为2个微服务,随着业务发展,业务功能越来越多,逻辑越来越复杂,团队扩展到12人,那么可以将已有的2个微服务进行拆分,变成4个微服务。

为什么是3个人?

  • 从系统规模来讲,3个人复杂开发一个系统,系统的复杂度刚好达到每个人都能全面理解整个系统,又能够进行分工的粒度。如果是2个人,系统的复杂度不够,开发人员可能觉得无法体现自己的技术实力;如果是4个甚至更多人开发一个系统,系统复杂度又会无法让开发人员对系统的细节都了解很深。
  • 从团队管理来说,3个人可以形成一个稳定的备份,即使1个人休假或者调配到其他系统,剩余2个人还可以支撑;如果是2个人,抽调1个后剩余的1个人压力很大;如果是1个人,这就是单点了,团队没有备份,某些情况下是很危险的,假如这个人休假了,系统出问题了怎么办?
  • 从技术提升的角度来讲,3个人的技术小组既能够形成有效的讨论,又能够快速达成一致意见;如果是2个人,可能会出现互相坚持自己的意见,或者2个人经验都不足导致设计缺陷;如果是1个人,由于没有人跟他进行技术讨论,很可能陷入思维盲区导致重大问题;如果是4个人或者更多,可能有的参与的人员并没有认真参与,只是完成任务而已。

“三个火枪手”原则主要应用于微服务设计和开发阶段,如果微服务后续发展比较稳定,处于维护期,无须太多的开发,那么平均1个人维护1个微服务甚至几个微服务都可以。考虑人员备份的情况,每个人微服务最好有2个人维护。

基于业务逻辑拆分

这是最常见的一种拆分方式,将系统中的业务按职责范围识别出来,每个单独的业务模块拆分为一个独立的服务。但在实践中最常见的问题是,“职责范围”难以达成一致意见。例如:一个电商系统,可以将服务划分为“商品”、“交易”、“用户”3个服务,也可以划分为“商品”、“订单”、“支付”、“发货”、“买家”、“卖家”等6个服务。哪种方式更合理,是不是越细越好呢?

导致这种困惑的主要根因在于从业务的角度来拆分的话,规模粗和规模细都没有问题,因为拆分基础都是业务逻辑,要判断拆分粒度,不能从业务逻辑角度,而要根据前面介绍的“三个火枪手”的原则,计算一下大概的服务数量范围,然后再确定合适的“职责范围”,否则就可能出现划分过粗或者过细的情况,而且大部分情况下会出现过细的情况。

例如:如果团队规模是10个人,按照“三个火枪手”原则计算,大约需要划分为4个服务,那么“登录、注册、用户信息管理”都可以划到“用户服务”职责范围内;如果团队规模是100人,服务数量可以达到40个,那么“用户登录“就是一个服务了;如果团队规模达到1000人,那“用户连接管理”可能就是一个独立的服务了。

基于可扩展拆分

将系统中的业务模块按照稳定性排序,将已经成熟和改动不大的服务拆分为稳定服务,将经常变化和迭代的服务拆分为变动服务。稳定的服务粒度可以粗一些,即使逻辑上没有强关联的服务,也可以放在同一个子系统中,例如将“日志服务”和“升级服务”放在同一个子系统中;不稳定的服务粒度可以细一些,但也不要太细,始终记住要控制服务的总数量

这样拆分主要是为了提升项目快速迭代的效率,避免在开发的时候,不小心影响了已有的成熟功能导致线上问题。

基于可靠性拆分

将系统中的业务模块按照优先级排序,将可靠性要求高的核心服务和可靠性要求低的非核心服务拆分开来,然后重点保证核心服务的高可用。具体拆分的时候,核心服务可以是一个也可以是多个,只要最终的服务数量满足“三个火枪手”原则就可以。

这样拆分带来的好处是:

  • 避免非核心服务故障影响核心服务
  • 核心服务高可用方案更加简单
  • 能够降低高可用成本

基于性能拆分

基于性能拆分和基于可靠性拆分类似,将性能要求高或者性能压力大的模块拆分出来,避免性能压力大的服务影响其他服务。常见的拆分方式和具体的性能瓶颈有关,可以拆分Web服务、数据库、缓存等。例如电商的抢购,性能压力最大的是入口的排队功能,可以将排队功能独立为一个服务。

注意:以上的拆分方法不是多选一,而是可以根据实际情况自由排列组合,但要控制好最终的服务数量尽量满足“三个火枪手”原则。

基础设施

虽然建设完善的微服务基础设施是一项大工程,但如果微服务数量不多的话,并不是每个基础设施都是必须的。此外,现在已经有一些开源的微服务基础设施全家桶了,比如 Spring Cloud、Spring Clound Alibaba、Dubbo 等。通常情况下,可按照下面优先级来搭建基础设施:

  1. 服务发现、服务路由、服务容错:这是最基本的微服务基础设施。
  2. 接口框架、API网关:主要是为了提升开发消息。接口框架是提升内部服务的开发效率,API网关是为了提升与外部服务对接的效率。
  3. 自动化部署、自动化测试和配置中心:提升测试和运维效率。
  4. 服务监控、服务跟踪、服务安全:进一步提升运维效率。

以上3和4两类基础设施,其重要性会随着微服务节点数量增加而越来越重要,但在微服务节点数量较少的时候,可以通过人工的方式支撑,虽然效率不高,但也基本能够顶住。

服务发现

特性NacosEurekaConsulZookeeper
一致性协议CP + APAPCPCP
健康检查TCP/HTTP/MySQL/ClientBeatClientBeatTCP/HTTP/gRPC/CMDKeepAlive
负载均衡权重/Metadata/SelectorRibbonFabio-
雪崩保护
访问协议HTTP/DNSHTTPHTTP/DNSTCP
多数据中心支持支持支持不支持
跨注册中心同步支持不支持支持不支持
Spring Cloud 集成支持支持支持支持
Dubbo 集成支持不支持支持支持
k8s 集成支持不支持支持不支持

Nacos

Eureka

Eureka 采用C/S架构,分为服务端和客户端两部分:

  • Eureka Server:作为服务注册中心,负责管理所有可用的服务实例信息(即服务注册表),并提供服务的注册、发现和状态监控。
  • Eureka Client:作为服务提供者或服务消费者,主要用于和 Eureka Server 进行交互。Client 默认每隔30秒会向 Server 发送心跳,若 Server 在多个心跳周期内(默认 90 秒)没有接收到某个 Client 的心跳,Server 将它从可用服务列表中移除。

注意

Eureka 2.0 已经停止维护。

Consul

  • Client Agent:部署在每一个服务节点上。
    1. 服务注册:将本地服务的元数据转发给 Server。
    2. 健康检查:执行本地服务及其依赖(如端口、脚本)的健康检查。
    3. 转发查询:将服务发现或配置查询的 RPC 请求转发给 Server 集群。
  • Server Agent:组成 Consul 的核心管理集群(通常3或5个节点)。它包含了 Client 的所有功能,并额外负责:
    1. 维护状态:通过 Raft 共识算法维护服务目录、配置信息的一致性与高可用。
    2. 响应RPC请求:直接处理客户端的服务发现和配置查询请求。
    3. 跨数据中心通信:通过 WAN Gossip 协议与其他数据中心的 Server 通信。

服务端代理(Server Agent)需要以单独的节点进行部署,不应与业务服务部署在同一节点上;而客户端代理(Client Agent)则必须与每一个业务服务实例部署在同一节点。

Zookeeper

ZooKeeper 本质上是一个分布式协调服务,其核心是一个基于 Paxos 算法变种(ZAB 协议)的、强一致性的分布式键值存储。它并非一个专门的服务发现工具,但可以利用其特性实现服务发现。

  • Leader:集群的唯一主节点,负责处理所有写请求。它通过 ZAB 协议将数据变更同步到所有 Follower 和 Observer,保证数据的强一致性。
  • Follower:参与投票选举 Leader 和参与写操作的一致性协议过程。它处理客户端的读请求,并将写请求转发给 Leader。
  • Observer:与 Follower 类似,处理读请求并转发写请求,但不参与任何投票。它的存在纯粹是为了扩展集群的读性能,而不影响写操作的效率。
  • ZNode:这是 ZooKeeper 数据模型的核心。它指的是数据树中的一个节点。ZNode 不仅可以存储少量数据(通常用于存储服务实例的元数据,如IP、端口),还可以通过创建临时节点(Ephemeral ZNode) 来实现服务发现和健康检查。

接口框架

微服务提倡轻量级的通信方式,一般采用HTTP/REST或者rpc方式统一接口协议,此外还要统一接口格式。比如使用HTTP/REST的数据要统一为如下的Json格式:

json
{
  "requestId": 10001,
  "time": "2025-09-14 11:20:00",
  "caller": "app1",
  "api": "getUser",
  "params": {
    "userId": 100
  },
  "sign": "xxx"
}

API网关

系统拆分为微服务后,内部的微服务之间是互联互通的,相互之间是点对点访问。如果外部系统想要调用系统内部的某个功能接口,也采用点对点方式,那外部系统的开发人员将会崩溃。因为外部系统不需要也没办法理解这么多微服务的职责分工和边界,它只会关注它需要的功能,而不会关注这个功能应该由哪个微服务提供。

除此以外,外部系统访问系统还涉及安全和权限相关的限制,如果外部系统直接访问某个微服务,则意味着每个微服务都要自己实现安全和权限的功能,这样做不但工作量大,而且都是重复工作。

综合上面的分析,微服务需要一个统一的API网关,负责外部系统的访问操作。API网关是外部系统访问的接口,所有的外部系统接⼊系统都需要通过API网关,主要包括接入鉴权(是否允许接入)、权限控制(可以访问哪些功能)、传输加密、请求路由、流量控制等功能。