本次优化主要有两部分,服务自动注销以及负载均衡策略。
之前demo可以实现服务的本地注册和Nacos远程服务注册。但是如果服务端断开,nacos注册中心中仍然存在未注销的服务信息,客户端继续调用该服务端提供的服务就会调用失败。因此需要在服务提供端关闭时自动向Nacos中心注册,这样要么在Nacos中找不到对应服务名,要么找得到服务名但是是其他服务端提供,仍然可以调用成功。
多次请求高并发的时候如果同时访问一个服务端会影响性能,因此负载均衡策略就是客户端在请求服务时通过合适的策略来选择不同的服务端。
基础逻辑
- 服务主动注销:获取该服务端本地已注册服务表,遍历其中服务,在nacos远程服务中心中依次注销。使用hook函数在JVM退出前调用主动注销的方法。注意本地服务表随着服务端断开JVM退出而销毁,不需要注销。
- 服务端选择的负载均衡策略:本例还是按照之前的只有一个服务端来提供,虽然测试上不会体现出负载均衡,但是主要是搞懂就好。。
知识点
步骤
一、 服务主动注销
-
在NettyRpcServer类中增加一个clearService方法,主要作用就是增加一个hook函数,在JVM退出之前调用新建线程中的语句块,也就是注销服务的具体操作。
//关闭前注销服务 public void clearService(){ logger.info("服务端关闭后在远程服务注册中心注销对应提供服务"); Runtime.getRuntime().addShutdownHook(new Thread( ()->{ Set<String> registeredService = localServiceRegistry.getRegisteredService(); remoteServiceRegistry.clearService(registeredService,host,port); logger.info("注销服务成功"); } )); }
注销服务首先要获取该服务端提供的本地已注册服务表registeredService。
注意由于NettyRpcServer类可以存在多个对象也就是多个服务提供端,其提供的服务并不相同,因此DefaultServiceRegistry中存放服务的容器应该是非静态的成员变量。
private final Map<String,Object> serviceMap = new ConcurrentHashMap<>(); private final Set<String> registeredService = ConcurrentHashMap.newKeySet(); public Set<String> getRegisteredService(){ return registeredService; }
接下来是在远程服务注册中心注销服务,在2中体现。
clearService方法注册hook函数的位置任意,本例为
finally { // hook,关闭前注销服务 clearService