Skip to content
清晨的一缕阳光
返回

Nacos 服务注册发现

Nacos 服务注册发现

Nacos 简介

Nacos(Naming and Configuration Service)是阿里巴巴开源的动态服务发现、配置管理和服务管理平台。

核心概念

工作原理

┌─────────────┐      注册       ┌─────────────┐
│  服务提供者  │ ──────────────> │   Nacos     │
│  Provider   │                 │   Server    │
└─────────────┘                 └─────────────┘

                                       │ 查询

┌─────────────┐                 ┌─────────────┐
│  服务消费者  │ <────────────── │   Nacos     │
│  Consumer   │   返回实例列表   │   Server    │
└─────────────┘                 └─────────────┘

快速开始

1. 添加依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2. 配置 Nacos

spring:
  application:
    name: user-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        namespace: public
        group: DEFAULT_GROUP
        cluster-name: DEFAULT
        register-enabled: true
        watch-enabled: true

3. 启用服务发现

@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

4. 服务调用

@RestController
public class UserController {
    
    @Autowired
    private DiscoveryClient discoveryClient;
    
    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
        // 获取服务实例列表
        List<ServiceInstance> instances = 
            discoveryClient.getInstances("order-service");
        
        // 负载均衡选择实例
        ServiceInstance instance = instances.get(0);
        
        // 调用服务
        String url = instance.getUri() + "/orders/" + id;
        return restTemplate.getForObject(url, User.class);
    }
}

高级特性

1. 命名空间隔离

使用命名空间实现环境隔离:

spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        namespace: 90a8c8b9-xxxx-xxxx-xxxx-xxxxxxxxxxxx  # dev 环境

最佳实践

2. 服务分组

使用分组实现服务版本管理:

spring:
  cloud:
    nacos:
      discovery:
        group: V1_GROUP  # 或 V2_GROUP

使用场景

3. 集群配置

将服务实例划分到不同集群:

spring:
  cloud:
    nacos:
      discovery:
        cluster-name: HANGZHOU  # 杭州集群

跨集群调用

@FeignClient(
    name = "order-service",
    configuration = FeignConfiguration.class
)
public interface OrderClient {
    @GetMapping("/orders/{id}")
    Result<Order> getOrder(@PathVariable("id") Long id);
}

@Configuration
public class FeignConfiguration {
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.BASIC;
    }
}

4. 元数据管理

为服务实例添加元数据:

spring:
  cloud:
    nacos:
      discovery:
        metadata:
          version: 1.0.0
          region: hangzhou
          zone: zone1

元数据使用

// 基于元数据的路由规则
@Autowired
private DiscoveryClient discoveryClient;

public ServiceInstance selectInstance() {
    List<ServiceInstance> instances = 
        discoveryClient.getInstances("order-service");
    
    return instances.stream()
        .filter(instance -> 
            "hangzhou".equals(instance.getMetadata().get("region"))
        )
        .findFirst()
        .orElse(instances.get(0));
}

健康检查

Nacos 健康检查机制

Nacos 支持两种健康检查模式:

  1. 客户端模式:服务实例主动上报心跳
  2. 服务端模式:Nacos 主动探测服务实例

配置健康检查

spring:
  cloud:
    nacos:
      discovery:
        # 心跳间隔(毫秒)
        heart-beat-interval: 5000
        # 心跳超时时间(毫秒)
        heart-beat-timeout: 15000
        # IP 保护时间(毫秒)
        ip-delete-timeout: 30000

自定义健康检查

@Component
public class CustomHealthCheck implements HealthCheckCallback {
    
    @Override
    public boolean doHealthCheck(String ip, int port) {
        // 自定义健康检查逻辑
        try {
            String url = "http://" + ip + ":" + port + "/health";
            ResponseEntity<String> response = 
                restTemplate.getForEntity(url, String.class);
            return response.getStatusCode().is2xxSuccessful();
        } catch (Exception e) {
            return false;
        }
    }
}

服务监听

监听服务变化

@Component
public class ServiceChangeListener {
    
    @Autowired
    private DiscoveryClient discoveryClient;
    
    @EventListener
    public void onInstanceEvent(InstanceEvent event) {
        if (event instanceof InstanceUpEvent) {
            log.info("服务上线:{}", event.getServiceId());
        } else if (event instanceof InstanceDownEvent) {
            log.info("服务下线:{}", event.getServiceId());
        }
    }
}

负载均衡

集成 Spring Cloud LoadBalancer

@Configuration
public class LoadBalancerConfiguration {
    
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
    @Bean
    public ReactorLoadBalancer<ServiceInstance> loadBalancer(
        Environment environment,
        LoadBalancerClientFactory loadBalancerClientFactory
    ) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return loadBalancerClientFactory.getInstance(name);
    }
}

自定义负载均衡策略

@Configuration
public class CustomLoadBalancerConfig {
    
    @Bean
    public ReactorServiceInstanceLoadBalancer loadBalancer() {
        return serviceInstances -> {
            List<ServiceInstance> list = serviceInstances.collectList().block();
            if (list == null || list.isEmpty()) {
                throw new NoServiceInstanceFoundException();
            }
            // 自定义选择逻辑
            return Mono.just(list.get(0));
        };
    }
}

生产实践

1. 多注册中心配置

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 
          - nacos1:8848
          - nacos2:8848
          - nacos3:8848

2. 服务优雅上下线

@Component
public class GracefulShutdown {
    
    @Autowired
    private NacosServiceRegistry serviceRegistry;
    
    @Autowired
    private NacosRegistration registration;
    
    @PreDestroy
    public void shutdown() {
        // 优雅下线
        serviceRegistry.deregister(registration);
        log.info("服务已优雅下线");
    }
}

3. 服务权重配置

spring:
  cloud:
    nacos:
      discovery:
        weight: 1.0  # 权重值,范围 0-1

4. 服务保护阈值

spring:
  cloud:
    nacos:
      discovery:
        protect-threshold: 0.2  # 保护阈值,低于此值不剔除实例

常见问题

1. 服务注册失败

问题:服务无法注册到 Nacos

排查步骤

2. 服务发现延迟

问题:服务上线后,消费者不能立即发现

解决方案

3. 服务实例重复

问题:同一服务出现多个相同实例

解决方案

总结

Nacos 作为服务注册中心,提供了服务自动注册与发现、健康检查、负载均衡等核心功能。

通过合理使用命名空间、分组、集群等特性,可以实现灵活的服务治理策略。

在生产环境中,建议配置合理的健康检查参数,并实现服务的优雅上下线,以提高系统的可用性。


分享这篇文章到:

上一篇文章
Spring Boot OAuth2 授权服务器
下一篇文章
MySQL COUNT 优化实战