栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

Nacos源码

Nacos源码

一.Nacos源码搭建
源码地址:
git clone https://gitee.com/mirrors/Nacos.git
启动问题1.找不到类
在ideal控制台使用:mvn compile

启动问题2.服务找不到(nacos默认使用集群形式)
-Dnacos.standalone=true


二. Nacos服务注册流程

进行服务注册

NamingProxy 366行 

使用了故障转移的算法 
大致思路:如果有5个注册中心,那么会随机取一个服务请求注册如果注册成功直接返回,如果注册失败就会尝试下一个,如果所有的都注册失败则直接抛出异常
疑问:只在一个上注册,那么其他服务是怎么知道到这个服务注册的呢? 猜测应该是用了定时任务拉取后做的同步数据
 public String reqAPI(String api, Map params, List servers, String method) {
        params.put("namespaceId", this.getNamespaceId());
        if (CollectionUtils.isEmpty(servers) && StringUtils.isEmpty(this.nacosDomain)) {
            throw new IllegalArgumentException("no server available");
        } else {
            Exception exception = new Exception();
            if (servers != null && !servers.isEmpty()) {
                Random random = new Random(System.currentTimeMillis());//根据当前时间创建随机数
                int index = random.nextInt(servers.size());//根据服务数量获取随机数

                for(int i = 0; i < servers.size(); ++i) {
                    String server = (String)servers.get(index);//获取随机的注册地址

                    try {
                        return this.callServer(api, params, server, method);//调用nacos注册中心
                    } catch (NacosException var11) {
                        exception = var11;
                        LogUtils.NAMING_LOGGER.error("request {} failed.", server, var11);
                    } catch (Exception var12) {
                        exception = var12;
                        LogUtils.NAMING_LOGGER.error("request {} failed.", server, var12);
                    }

                    index = (index + 1) % servers.size();//出现异常请求下一个
                }

                throw new IllegalStateException("failed to req API:" + api + " after all servers(" + servers + ") tried: " + ((Exception)exception).getMessage());
            } else {
                int i = 0;

                while(i < 3) {
                    try {
                        return this.callServer(api, params, this.nacosDomain);
                    } catch (Exception var13) {
                        exception = var13;
                        LogUtils.NAMING_LOGGER.error("[NA] req api:" + api + " failed, server(" + this.nacosDomain, var13);
                        ++i;
                    }
                }

                throw new IllegalStateException("failed to req API:/api/" + api + " after all servers(" + servers + ") tried: " + ((Exception)exception).getMessage());
            }
        }
    }
通过httpclient发送请求到/nacos/v1/ns/instance
public String callServer(String api, Map params, String curServer, String method) throws NacosException {
        long start = System.currentTimeMillis();
        long end = 0L;
        this.checkSignature(params);
        List headers = this.builderHeaders();
        String url;//请求路径为:/nacos/v1/ns/instance
        if (!curServer.startsWith("https://") && !curServer.startsWith("http://")) {
            if (!curServer.contains(":")) {
                curServer = curServer + ":" + this.serverPort;
            }

            url = HttpClient.getPrefix() + curServer + api;
        } else {
            url = curServer + api;
        }

        HttpResult result = HttpClient.request(url, headers, params, "UTF-8", method);
        end = System.currentTimeMillis();
        MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(result.code)).observe((double)(end - start));
        if (200 == result.code) {
            return result.content;
        } else if (304 == result.code) {
            return "";
        } else {
            throw new NacosException(500, "failed to req API:" + curServer + api + ". code:" + result.code + " msg: " + result.content);
        }
    }

Nacos Server端

请求到服务端/nacos/v1/ns/instance地址--》InstanceController
	@CanDistro
    @PostMapping
    @Secured(parser = NamingResourceParser.class, action = ActionTypes.WRITE)
    public String register(HttpServletRequest request) throws Exception {
        
        final String namespaceId = WebUtils//根据namespaceId获取命名空间,如果没有则为默认public
                .optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
        final String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);//根据serviceName获取服务名
        NamingUtils.checkServiceNameFormat(serviceName);//服务名格式为DEFAULT_GROUP@@nacos-test
        
        final Instance instance = HttpRequestInstanceBuilder.newBuilder()//根据当前请求创建临时实例
                .setDefaultInstanceEphemeral(switchDomain.isDefaultInstanceEphemeral()).setRequest(request).build();
        
        getInstanceOperator().registerInstance(namespaceId, serviceName, instance);//注册实例
        return "ok";
    }

/这里是客户端请求会进入InstanceOperatorClientImpl

		boolean ephemeral = instance.isEphemeral();//判断是否是临时实例
        String clientId = IpPortbasedClient.getClientId(instance.toInetAddr(), ephemeral);//根据ip获取clientId——》127.0.0.1:8181#true
        createIpPortClientIfAbsent(clientId);//如果容器已有当前ip实例建立连接
        Service service = getService(namespaceId, serviceName, ephemeral);//创建服务实例
        clientOperationService.registerInstance(service, instance, clientId);//注册客户端实例
	@Override
    public void registerInstance(Service service, Instance instance, String clientId) {
        Service singleton = ServiceManager.getInstance().getSingleton(service);//获取服务单实例
        Client client = clientManager.getClient(clientId);
        if (!clientIsLegal(client, clientId)) {//判断连接是否已经断开或者不是临时连接
            return;
        }
        InstancePublishInfo instanceInfo = getPublishInfo(instance);//创建事件实例
        client.addServiceInstance(singleton, instanceInfo);
        client.setLastUpdatedTime();
        NotifyCenter.publishEvent(new ClientOperationEvent.ClientRegisterServiceEvent(singleton, clientId));
        NotifyCenter
                .publishEvent(new metadataEvent.InstancemetadataEvent(singleton, instanceInfo.getmetadataId(), false));//发布事件
    }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/618602.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号