服务发现

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

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

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

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

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

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

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

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

@Serviceclass 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 胜利时,打印一些信息。