乐趣区

关于微服务:微服务开发系列服务发现nacos-的小补充

服务发现

框架中的服务发现,应用的是 nacos 提供的。

nacos 提供的域的概念十分好用,可能很不便的将开发环境和本地环境辨别来开,有助于接口调试。

然而实现上也有一些毛病,那就是网关无奈获取到服务注册的事件,而且当服务启动时,网关会有几秒到十几秒的工夫,才可能发现注册的新服务,此时,才可能转发申请。

对于网关无奈获取到服务注册事件,Eureka 提供了 EurekalnstanceRegisteredEventEurekalnstanceCanceledEvent 等事件能够判断。

然而我没有在 nacos 下找到相似的办法,对此一开始我的解决方案是,本人做一个检测服务类 cn.gateway.core.InstanceDetect,将曾经注册上的服务保留,之后定时扫描,和保留的服务比照,如果新增就是注册胜利,如果不存在就是勾销注册。

不过最初,还是找到了绝对完满的解决办法,通过 NacosServiceManager,在 InstanceRegisteredEvent 事件触发后,也就是网关自身注册到 nacos 后,nacosServiceManager.getNamingService(null) 这段代码才可能获取到 namingService 对象。

最初就能够通过 GatewayProperties 获取到所有的服务名称,再进行对应的订阅即可。

可能实现这一点,还是因为 nacos 和 gateway 都是基于 spring.application.name 作为注册服务和转发服务的根据。

@Service
class InstanceDetect(
    private val nacosServiceManager: NacosServiceManager,
    private val gatewayProperties: GatewayProperties
) {
    @EventListener
    fun onApplicationEvent(event: InstanceRegisteredEvent<*>) {val namingService = nacosServiceManager.getNamingService(null)
        gatewayProperties.routes.forEach {val serviceInstanceMap = mutableMapOf<String, Instance>()
            namingService.subscribe(it.id) { event ->
                if (event !is NamingEvent) {return@subscribe}
                val serviceInstances = HashSet(serviceInstanceMap.keys)
                event.instances.forEach { instance ->
                    if (serviceInstances.contains(instance.instanceId)) {serviceInstances.remove(instance.instanceId)
                    } else {serviceInstanceMap[instance.instanceId] = instance
                        log.info("instance connected : {}, ip : {}, port : {}",
                            instance.instanceId, instance.ip, instance.port
                        )
                    }
                }
                for (removedInstance in serviceInstances) {val remove = serviceInstanceMap.remove(removedInstance)!!
                    log.info("instance disconnected : {}, ip : {}, port : {}",
                        removedInstance, remove.ip, remove.port
                    )
                }
            }
        }
    }
}

除此之外,客户端也提供了 RegisterEventListener 这个类,当客户端注册到 nacos 胜利时,打印一些信息。

退出移动版