Nacos框架服务主动下线原理及源代码讲解

 

原理:

       Nacos没有想eureka一样,在服务端提供API供调用进行服务下线,Nacos的实现方式是通过在客户端提供方法,我们自己封装API进行调用,然后客户端会进行2个步骤:

1,如果是临时服务,客户端会把自己发送续约保活心跳的缓存实例给删除掉。

2,向服务端发起删除服务请求到服务端。

第一步:操作完后,客户端不再向服务端发送心跳续约保活,因此给服务端造成客户端已死现象。

第二步:操作完后,服务端接收到该请求,会将该服务从服务列表删除掉,同时向各健康客户端发布一个change事件,告知服务列表更新了。

       这2步操作完成之后,nacos服务端和客户端之间,互不通信。Nacos服务端列表没有该服务健康列表,其他服务无法调用该服务。

服务再次上线方法:

       如果后续服务想要再次上线,要么重启服务,要么调用nacos提供的服务注册API,或者自己封装服务注册API。

代码:

1,用户在客户端 自实现服务优雅下线的API

 /**
     * Nacos 服务列表端的服务实例主动下线
     * @return
     */
    @RequestMapping("/api/nacos/deRegisterServer")
    @GetMapping
    public boolean deRegisterServer()
    {

        Instance instance = new Instance();

        instance.setIp(nacosDiscoveryProperties.getIp());
//        instance.setPort(port);

        instance.setPort(nacosDiscoveryProperties.getPort());

        instance.setClusterName(nacosDiscoveryProperties.getClusterName());

        instance.setServiceName(nacosDiscoveryProperties.getService());

        try {
            nacosRegistration.getNacosNamingService().deregisterInstance(nacosDiscoveryProperties.getService(),instance);
            return true;
        } catch (NacosException e) {
            e.printStackTrace();
            return false;
        }
    }

2,Nacos客户端提供的下线方法deregisterInstance

@Override
public void deregisterInstance(String serviceName, Instance instance) throws NacosException {
    deregisterInstance(serviceName, Constants.DEFAULT_GROUP, instance);
}

@Override
public void deregisterInstance(String serviceName, String groupName, Instance instance) throws NacosException {
    if (instance.isEphemeral()) {
        beatReactor.removeBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), instance.getIp(), instance.getPort());
    }
    serverProxy.deregisterService(NamingUtils.getGroupedName(serviceName, groupName), instance);
}

3,原理中的第一步操作

如果是临时服务,客户端会把自己发送续约保活心跳的缓存实例给删除掉。具体内容如下:

public void removeBeatInfo(String serviceName, String ip, int port) {
        NAMING_LOGGER.info("[BEAT] removing beat: {}:{}:{} from beat map.", serviceName, ip, port);
        BeatInfo beatInfo = dom2Beat.remove(buildKey(serviceName, ip, port));
        if (beatInfo == null) {
            return;
        }
        beatInfo.setStopped(true);
        MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
    }

dom2Beat是一个map集合,里面存放了BeatInfo对象,这个对象封装当前服务实例的ip,port等信息。

/**
 * @author nkorange
 */
public class BeatInfo {

    private int port;
    private String ip;
    private double weight;
    private String serviceName;
    private String cluster;
    private Map<String, String> metadata;
    private volatile boolean scheduled;
    private volatile long period;
    private volatile boolean stopped;

4,原理中的第二步

向服务端发起删除服务请求到服务端。具体内容如下

 public void deregisterService(String serviceName, Instance instance) throws NacosException {

        NAMING_LOGGER.info("[DEREGISTER-SERVICE] {} deregistering service {} with instance: {}",
            namespaceId, serviceName, instance);

        final Map<String, String> params = new HashMap<String, String>(8);
        params.put(CommonParams.NAMESPACE_ID, namespaceId);
        params.put(CommonParams.SERVICE_NAME, serviceName);
        params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());
        params.put("ip", instance.getIp());
        params.put("port", String.valueOf(instance.getPort()));
        params.put("ephemeral", String.valueOf(instance.isEphemeral()));

        reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.DELETE);
    }

最终执行到如下代码,客户端向服务端发送http请求,执行delete方法。

public String callServer(String api, Map<String, String> params, String curServer, String method)
        throws NacosException {
        long start = System.currentTimeMillis();
        long end = 0;
        checkSignature(params);
        List<String> headers = builderHeaders();

        String url;
        if (curServer.startsWith(UtilAndComs.HTTPS) || curServer.startsWith(UtilAndComs.HTTP)) {
            url = curServer + api;
        } else {
            if (!curServer.contains(UtilAndComs.SERVER_ADDR_IP_SPLITER)) {
                curServer = curServer + UtilAndComs.SERVER_ADDR_IP_SPLITER + serverPort;
            }
            url = HttpClient.getPrefix() + curServer + api;
        }

        HttpClient.HttpResult result = HttpClient.request(url, headers, params, UtilAndComs.ENCODING, method);
        end = System.currentTimeMillis();

        MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(result.code))
            .observe(end - start);

        if (HttpURLConnection.HTTP_OK == result.code) {
            return result.content;
        }

        if (HttpURLConnection.HTTP_NOT_MODIFIED == result.code) {
            return StringUtils.EMPTY;
        }

        throw new NacosException(NacosException.SERVER_ERROR, "failed to req API:"
            + curServer + api + ". code:"
            + result.code + " msg: " + result.content);
    }

服务下线服务后nacos后台管理服务列表:

服务再次上线,个人封装API:

/**
     * Nacos 服务列表端的服务实例上线
     * @return
     */
    @RequestMapping("/api/nacos/rgisterServer")
    @GetMapping
    public boolean rgisterServer()
    {

        Instance instance = new Instance();

        instance.setIp(nacosDiscoveryProperties.getIp());
//        instance.setPort(port);

        instance.setPort(nacosDiscoveryProperties.getPort());

        instance.setClusterName(nacosDiscoveryProperties.getClusterName());

        instance.setServiceName(nacosDiscoveryProperties.getService());

        try {
            nacosRegistration.getNacosNamingService().registerInstance(nacosDiscoveryProperties.getService(),instance);
            return true;
        } catch (NacosException e) {
            e.printStackTrace();
            return false;
        }
    }

服务上线服务后nacos后台管理服务列表:

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值