Nacos——服务订阅
1. 前提
当服务提供者注册实例到Nacos服务端后,服务消费者就需要订阅提供者服务来进行调用。常见的服务消费者有Dubbo消费者,Spring Cloud消费者,但由于没有使用过Dubbo和Spring Cloud从Nacos中订阅服务,而使用过Spring Cloud Gateway结合Nacos做服务化路由,所以会结合Spring Cloud Gateway来讲Nacos的服务订阅。
2. maven依赖
spring-cloud-starter-gateway: 2.2.5.RELEASE
spring-cloud-starter-alibaba-nacos-discovery: 2.2.4.RELEASE
nacos-client: 1.4.2
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.4.2</version>
</dependency>
3. 流程图

- 服务提供者注册实例到Nacos服务端集群
- 网关需要服务化路由时,订阅服务提供者的实例集合
- 根据负载均衡策略从实例集合中选择一个实例进行路由
4. 源码分析
-
启动时订阅自己
NacosDiscoveryClientConfiguration初始化NacosWatch@Bean @ConditionalOnMissingBean @ConditionalOnProperty(value = "spring.cloud.nacos.discovery.watch.enabled", matchIfMissing = true) public NacosWatch nacosWatch(NacosServiceManager nacosServiceManager, NacosDiscoveryProperties nacosDiscoveryProperties, ObjectProvider<ThreadPoolTaskScheduler> taskExecutorObjectProvider) { return new NacosWatch(nacosServiceManager, nacosDiscoveryProperties, taskExecutorObjectProvider); }NacosWatch实现了
SmartLifecycle接口,即在Spring容器生命周期启动和销毁时执行相关操作,对应start()和stop()private final AtomicBoolean running = new AtomicBoolean(false); private Map<String, EventListener> listenerMap = new ConcurrentHashMap<>(16); @Override public void start() { if (this.running.compareAndSet(false, true)) { // 事件监听处理器 EventListener eventListener = listenerMap.computeIfAbsent(buildKey(), event -> new EventListener() { @Override public void onEvent(Event event) { if (event instanceof NamingEvent) { List<Instance> instances = ((NamingEvent) event) .getInstances(); // 筛选出当前实例 Optional<Instance> instanceOptional = selectCurrentInstance( instances); // 更新元数据 instanceOptional.ifPresent(currentInstance -> { resetIfNeeded(currentInstance); }); } } }); // 获取NamingService NamingService namingService = nacosServiceManager .getNamingService(properties.getNacosProperties()); try { // 订阅自己 namingService.subscribe(properties.getService(), properties.getGroup(), Arrays.asList(properties.getClusterName()), eventListener); } catch (Exception e) { log.error("namingService subscribe failed, properties:{}", properties, e); } // 发布HeartbeatEvent事件 this.watchFuture = this.taskScheduler.scheduleWithFixedDelay( this::nacosServicesWatch, this.properties.getWatchDelay()); } } /** * 从实例集合中筛选出当前ip和端口的实例 */ private Optional<Instance> selectCurrentInstance(List<Instance> instances) { return instances.stream() .filter(instance -> properties.getIp().equals(instance.getIp()) && properties.getPort() == instance.getPort()) .findFirst(); } /** * 订阅到的实例元数据不同则更新 */ private void resetIfNeeded(Instance instance) { if (!properties.getMetadata().equals(instance.getMetadata())) { properties.setMetadata(instance.getMetadata()); } } /** * 发布HeartbeatEvent事件用于消费者进行更新操作 * 比如 Spring Cloud Gateway中的RouteRefreshListener */ public void nacosServicesWat
4186




被折叠的 条评论
为什么被折叠?



