微服务注册中心详解:Eureka vs Nacos,原理与实践 | 一站式掌握服务注册、发现与负载均衡

🔍 微服务注册中心的核心挑战

想象一下,当我们的服务提供者(如 user-service)部署了多个实例时(如下图),会面临几个关键问题:

  1. 服务发现 :服务消费者(如 order-service)如何动态感知 user-service 实例的 IP 和端口?
  2. 负载均衡 :面对多个 user-service 实例,order-service 如何智能选择调用目标?
  3. 健康监测order-service 如何实时判断某个 user-service 实例是否存活?

🛠 解决方案:注册中心

这些问题正是 注册中心(Registry) 的核心作用!Spring Cloud 生态中,EurekaNacos 是两大主流选择。

📡 Eureka 的工作原理

  • 服务注册user-service 启动时,向 Eureka Server 注册自身信息(服务名、IP、端口等)。
  • 服务发现order-service 根据服务名(如 userservice)从 Eureka Server 拉取可用的实例列表。
  • 负载均衡order-service 使用算法(如轮询)从列表中选择一个实例发起调用。
  • 健康检查user-service 定期(默认 30 秒)发送心跳 给 Eureka Server。若长时间无心跳,Eureka Server 会将其从列表剔除

💡 提示:一个微服务可同时是提供者和消费者,注册/发现逻辑统一封装在 eureka-client 组件中。

🚀 快速搭建 Eureka Server

  1. 创建独立服务模块 ( eureka-server)

在cloud-demo父工程下,创建一个子模块:

  1. 添加依赖 (pom.xml):

    引入SpringCloud为eureka提供的starter依赖:

    xml 复制代码
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
  2. 编写启动类 (添加 @EnableEurekaServer)

    给eureka-server服务编写一个启动类,一定要添加一个 @EnableEurekaServer注解,开启eureka的注册中心功能:

    less 复制代码
    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaApplication.class, args);
        }
    }
  1. 配置文件 (application.yml):

    编写一个application.yml文件,内容如下:

    yaml 复制代码
    server:
      port: 10086
    spring:
      application:
        name: eurekaserver
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:10086/eureka # 单机指向自己
  2. 启动并访问http://localhost:10086

📝 服务注册与发现实践

  1. 服务注册 (user-service)

    • 添加依赖 (eureka-client客户端依赖)

    在user-service的pom文件中,引入下面的eureka-client依赖:

    xml 复制代码
    <!--eureka客户端依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    • 配置

      在user-service中,修改application.yml文件,添加服务名称、eureka地址:

      yaml 复制代码
      spring:
        application:
          name: userservice # 服务名
      eureka:
        client:
          service-url:
            defaultZone: http://localhost:10086/eureka # Eureka地址
    • 启动多个实例(不同端口)后,即可在 Eureka 控制台看到注册信息。

    为了演示一个服务有多个实例的场景,我们添加一个SpringBoot的启动配置,再启动一个user-service。

    首先,复制原来的user-service启动配置:

然后,在弹出的窗口中,填写信息:

启动两个user-service实例:

查看eureka-server管理页面:

  1. 服务发现与调用 (order-service)

下面,我们将order-service的逻辑修改:向eureka-server拉取user-service的信息,实现服务发现。

  • 添加依赖 (eureka-client客户端依赖)

服务发现、服务注册统一都封装在eureka-client依赖,因此这一步与服务注册时一致。

在order-service的pom文件中,引入下面的eureka-client依赖:

xml 复制代码
<!--eureka客户端依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  • 配置 (同上,服务名改为 orderservice)

在order-service中,修改application.yml文件,添加服务名称、eureka地址:

yaml 复制代码
 spring:
   application:
     name: orderservice #Order服务的服务名称
 eureka:
   client:
     service-url:
       defaultZone: http://localhost:10086/eureka # Eureka地址
  • 服务拉取和负载均衡

我们要去eureka-server中拉取user-service服务的实例列表,并且实现负载均衡。

不过这些动作不用我们去做,只需要添加一些注解即可, 在order-service的OrderApplication中,给RestTemplate这个Bean添加一个

  • RestTemplate Bean 添加 @LoadBalanced 注解。
  • 使用服务名 发起调用:http://userservice/user/1 (Spring Cloud 自动处理地址转换)。

修改order-service服务中的order.service包下的OrderService类中的queryOrderById方法。修改访问的url路径,用服务名代替ip、端口:

⚖️ Ribbon:负载均衡引擎

@LoadBalanced 背后的功臣是 Ribbon的组件,来实现负载均衡功能的。

🔬 Ribbon 工作原理

  1. 拦截请求LoadBalancerInterceptor 拦截 RestTemplate 发出的请求 (http://userservice/user/1)。
  2. 提取服务名 :获取 URL 中的主机名 (userservice)。
  3. 拉取服务列表 :向注册中心 (Eureka) 请求 userservice 的可用实例列表。
  4. 负载均衡 :使用 IRule 算法 (默认 RoundRobinRule 轮询) 选择一个实例 ( localhost:8081)。
  5. 重构请求 :将原 URL 中的服务名替换为选中的实例地址 ( http://localhost:8081/user/1)。
  6. 发起真实调用

🎯 负载均衡策略 (IRule)

负载均衡的规则都定义在IRule接口中,而IRule有很多不同的实现类:

不同规则的含义如下:

策略类 规则描述
RoundRobinRule 默认策略。简单轮询服务列表。
RandomRule 随机选择一个可用实例。
ZoneAvoidanceRule 推荐。优先选择同区域 (Zone) 的实例,区域内再做轮询。优化延迟和故障。
AvailabilityFilteringRule 忽略多次连接失败或并发过高的服务器。
WeightedResponseTimeRule 根据实例响应时间分配权重,响应越快权重越高。
BestAvailableRule 选择并发请求数最低的实例。
RetryRule 带有重试机制的轮询。

自定义策略 (以 RandomRule 为例):

  • 代码方式

    在order-service中的OrderApplication类中,定义一个新的IRule:

    typescript 复制代码
    @Bean
    public IRule randomRule() {
        return new RandomRule(); // 随机策略
    }
  • 配置文件方式 (order-serviceapplication.yml):

    添加新的配置也可以修改规则

    yaml 复制代码
    userservice: # 指定对哪个服务生效
      ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

⚡ 性能优化:饥饿加载 (Eager Loading)

Ribbon 默认懒加载 ,即第一次访问时才会去创建LoadBalanceClient首次请求耗时较长。开启饥饿加载可在应用启动时初始化负载均衡客户端:

通过下面配置开启饥饿加载yaml

yaml 复制代码
ribbon:
  eager-load:
    enabled: true # 开启饥饿加载
    clients: userservice # 指定对哪些服务进行饥饿加载 (可多个)

🚀 Nacos:更强大的注册中心

Nacos 是阿里巴巴的产品,现在是SpringCloud中的一个组件。相比Eureka功能更加丰富,在国内受欢迎程度较高。

🛠 Nacos 安装与启动

  1. 下载 Nacos Server。

  2. 启动 (单机模式):进入 bin 目录执行:

    bash

    bash 复制代码
    startup.cmd -m standalone # Windows
    sh startup.sh -m standalone # Linux/macOS
  3. 访问控制台http://localhost:8848/nacos (默认账号/密码:nacos)。

🔧 服务注册到 Nacos

Nacos是SpringCloudAlibaba的组件,而SpringCloudAlibaba也遵循SpringCloud中定义的服务注册、服务发现规范。因此使用Nacos和使用Eureka对于微服务来说,并没有太大区别。

主要差异在于:

  • 依赖不同
  • 服务地址不同
  1. 添加依赖

    在cloud-demo父工程的pom文件中的<dependencyManagement>中引入SpringCloudAlibaba的依赖:

    xml 复制代码
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.2.6.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>

    然后在user-service和order-service中的pom文件中引入nacos-discovery依赖:

    xml 复制代码
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

    ⚠️ 记得移除或注释掉 eureka-client 依赖。

  2. 配置地址 (application.yml):

    在user-service和order-service的application.yml中添加nacos地址:

    yaml 复制代码
    spring:
      cloud:
        nacos:
          server-addr: localhost:8848 # Nacos Server 地址

    ⚠️ 记得移除或注释掉 eureka 的地址。

  3. 重启服务,在 Nacos 控制台 服务管理 > 服务列表 中查看注册信息。

🌐 Nacos 高级特性

一个服务 可以有多个实例,例如我们的user-service,可以有:

  • 127.0.0.1:8081
  • 127.0.0.1:8082
  • 127.0.0.1:8083

假如这些实例分布于全国各地的不同机房,例如:

  • 127.0.0.1:8081,在上海机房
  • 127.0.0.1:8082,在上海机房
  • 127.0.0.1:8083,在杭州机房

Nacos就将同一机房内的实例 划分为一个集群

也就是说,user-service是服务,一个服务可以包含多个集群,如杭州、上海,每个集群下可以有多个实例,形成分级模型,如图:

微服务互相访问时,应该尽可能访问同集群实例,因为本地访问速度更快。当本集群内不可用时,才访问其它集群。例如:

杭州机房内的order-service应该优先访问同机房的user-service。

  1. 服务分级模型 (集群)

    • 概念 :将同一机房/地域的实例划分到一个集群 (Cluster)

    • 优势 :优先访问同集群实例,降低延迟;跨集群访问作为容灾后备。

    • 配置 (实例的 application.yml):

      修改user-service的application.yml文件,添加集群配置:

      yaml 复制代码
      spring:
        cloud:
          nacos:
            discovery:
              cluster-name: SZ # 集群名称 (如 SZ-深圳, HZ-杭州)

      重启两个user-service实例后,我们可以在nacos控制台看到下面结果:

  1. 同集群优先负载均衡

    默认的ZoneAvoidanceRule并不能实现根据同集群优先来实现负载均衡。

    因此Nacos中提供了一个NacosRule的实现,可以优先从同集群中挑选实例。

    • 配置 order-service 的集群 (同上)。

    • 修改负载均衡规则为 NacosRule (order-serviceapplication.yml):

      修改负载均衡规则:

      yaml 复制代码
      userservice: # 服务提供者名称
        ribbon:
          NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # Nacos集群优先策略
  2. 权重配置

但默认情况下NacosRule是同集群内随机挑选,不会考虑机器的性能问题,因此,Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高。

  • 场景:根据机器性能分配流量。
  • 操作 :在 Nacos 控制台 > 服务详情 > 实例列表 > 编辑实例,修改权重 (0-1, 权重越大访问频率越高)。权重为 0 则完全不被访问。

4. 环境隔离 (Namespace)

Nacos提供了namespace来实现环境隔离功能,nacos中可以有多个namespace,namespace下可以有group、service等

  • 场景:隔离开发、测试、生产等环境。

  • 操作

    1. Nacos 控制台 > 命名空间 > 创建命名空间 (dev, test, prod),获取生成的 Namespace ID

    2. 微服务配置:

      修改order-service的application.yml文件:

      yaml 复制代码
      spring:
        cloud:
          nacos:
            discovery:
              namespace: 492a7d5d-237b-46a1-a99a-fa8e98e4b0f9 # 填入目标Namespace ID
  • 效果 :不同 Namespace 的服务相互不可见

⚖️ Nacos vs Eureka 核心区别

特性 Nacos Eureka
实例类型 临时实例 (默认):心跳异常自动剔除。 非临时实例 (ephemeral: false):不自动剔除,需主动下线。 所有实例均为临时实例,心跳异常自动剔除。
健康检查 主动探测 (对非临时实例) + 心跳 心跳
服务列表更新 推送模式 (变更实时性强)。 定时拉取 (有延迟)。
CAP 模型 临时实例:AP 。 存在非临时实例:CP AP
额外功能 配置中心权重集群命名空间 核心注册与发现。

配置非临时实例 (Nacos):

yaml 复制代码
spring:
  cloud:
    nacos:
      discovery:
        ephemeral: false # 设置为非临时实例

总结

Nacos和Eureka整体结构类似,服务注册、服务拉取、心跳等待,但是也存在一些差异

  • Eureka:Spring Cloud Netflix 原生方案,简单可靠,AP 模型保证高可用。
  • Nacos:功能强大 (注册中心 + 配置中心),支持集群、权重、环境隔离,健康检查更灵活 (支持主动探测和临时/非临时实例),国内生态活跃。

根据项目需求和团队技术栈选择合适的注册中心!💪🏻

相关推荐
提笔了无痕20 小时前
git基本了解、常用基本命令与使用
git·后端
java1234_小锋20 小时前
Spring IoC的实现机制是什么?
java·后端·spring
喵个咪20 小时前
开箱即用的 GoWind Admin|风行,企业级前后端一体中后台框架:JWT 集成指南
后端·go
绝不收费—免费看不了了联系我21 小时前
Fastapi的单进程响应问题 和 解决方法
开发语言·后端·python·fastapi
喵个咪21 小时前
开箱即用的 GoWind Admin|风行,企业级前后端一体中后台框架:OPA 集成指南:从原理到实践
后端·go
Victor35621 小时前
Netty(11) Netty的心跳机制是什么?为什么需要它?
后端
Victor3561 天前
Netty(12)Netty支持哪些协议和传输方式?
后端
无限大61 天前
为什么电脑需要"内存"和"硬盘"?——存储金字塔的秘密
后端
ovensi1 天前
Docker+NestJS+ELK:从零搭建全链路日志监控系统
后端·nestjs
武子康1 天前
大数据-184 Elasticsearch Doc Values 机制详解:列式存储如何支撑排序/聚合/脚本
大数据·后端·elasticsearch