nacos-1.4.1客户端启动,注册服务源码分析

文章目录


启动流程

项目入口,boot自动装配

在这里插入图片描述
点进com.alibaba.cloud.nacos.NacosDiscoveryAutoConfiguration类

@Configuration
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class,
		AutoServiceRegistrationAutoConfiguration.class })
public class NacosDiscoveryAutoConfiguration {

	@Bean
	public NacosServiceRegistry nacosServiceRegistry(
			NacosDiscoveryProperties nacosDiscoveryProperties) {
		return new NacosServiceRegistry(nacosDiscoveryProperties);
	}

	@Bean
	@ConditionalOnBean(AutoServiceRegistrationProperties.class)
	public NacosRegistration nacosRegistration(
			NacosDiscoveryProperties nacosDiscoveryProperties,
			ApplicationContext context) {
		return new NacosRegistration(nacosDiscoveryProperties, context);
	}

	@Bean
	@ConditionalOnBean(AutoServiceRegistrationProperties.class)
	public NacosAutoServiceRegistration nacosAutoServiceRegistration(
			NacosServiceRegistry registry,
			AutoServiceRegistrationProperties autoServiceRegistrationProperties,
			NacosRegistration registration) {
		return new NacosAutoServiceRegistration(registry,
				autoServiceRegistrationProperties, registration);
	}
}

关键代码
这里将NacosAutoServiceRegistration作为Bean注入。那么点进NacosAutoServiceRegistration类看看发生了什么?

public class NacosAutoServiceRegistration extends AbstractAutoServiceRegistration<Registration> {
	...省略无关代码
}

在来看看父类AbstractAutoServiceRegistration。发现父类AbstractAutoServiceRegistration声明了ApplicationListener接口,需要实现

public abstract class AbstractAutoServiceRegistration<R extends Registration> 
implements AutoServiceRegistration, ApplicationContextAware, ApplicationListener<WebServerInitializedEvent> {
	...省略无关代码
	public void onApplicationEvent(WebServerInitializedEvent event) {
	    this.bind(event);
	}
}

当spring加载完成,事件通知时,就会执行bind方法。进行追踪

@Deprecated
public void bind(WebServerInitializedEvent event) {
    ApplicationContext context = event.getApplicationContext();
    if (!(context instanceof ConfigurableWebServerApplicationContext) || !"management".equals(((ConfigurableWebServerApplicationContext)context).getServerNamespace())) {
        this.port.compareAndSet(0, event.getWebServer().getPort());
        //关键代码
        this.start();
    }
}
public void start() {
    if (!this.isEnabled()) {
        if (logger.isDebugEnabled()) {
            logger.debug("Discovery Lifecycle disabled. Not starting");
        }

    } else {
        if (!this.running.get()) {
            this.context.publishEvent(new InstancePreRegisteredEvent(this, this.getRegistration()));
            //关键代码
            this.register();
            if (this.shouldRegisterManagement()) {
                this.registerManagement();
            }

            this.context.publishEvent(new InstanceRegisteredEvent(this, this.getConfiguration()));
            this.running.compareAndSet(false, true);
        }

    }
}
protected void register() {
    this.serviceRegistry.register(this.getRegistration());
}

点开register实现类

public class NacosServiceRegistry implements ServiceRegistry<Registration> {
    ...省略无关代码
    public void register(Registration registration) {
        if (StringUtils.isEmpty(registration.getServiceId())) {
            log.warn("No service to register for nacos client...");
        } else {
            String serviceId = registration.getServiceId();
            Instance instance = this.getNacosInstanceFromRegistration(registration);

            try {
                //注册实例
                this.namingService.registerInstance(serviceId, instance);
                log.info("nacos registry, {} {}:{} register finished", new Object[]{serviceId, instance.getIp(), instance.getPort()});
            } catch (Exception var5) {
                log.error("nacos registry, {} register failed...{},", new Object[]{serviceId, registration.toString(), var5});
            }

        }
    }
}

进入类com.alibaba.nacos.client.naming.NacosNamingService

@Override
public void registerInstance(String serviceName, Instance instance) throws NacosException {
    //注册实例
    registerInstance(serviceName, Constants.DEFAULT_GROUP, instance);
}

@Override
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
    NamingUtils.checkInstanceIsLegal(instance);
    String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);
    if (instance.isEphemeral()) {
        BeatInfo beatInfo = beatReactor.buildBeatInfo(groupedServiceName, instance);
        beatReactor.addBeatInfo(groupedServiceName, beatInfo);
    }
   	//关键代码
    serverProxy.registerService(groupedServiceName, groupName, instance);
}

类com.alibaba.nacos.client.naming.net.NamingProxy

/**
 * 使用指定的实例属性将实例注册到服务。
 * register a instance to service with specified instance properties.
 *
 * @param serviceName name of service
 * @param groupName   group of service
 * @param instance    instance to register
 * @throws NacosException nacos exception
 */
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {

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

    final Map<String, String> params = new HashMap<String, String>(16);
    params.put(CommonParams.NAMESPACE_ID, namespaceId);
    params.put(CommonParams.SERVICE_NAME, serviceName);
    params.put(CommonParams.GROUP_NAME, groupName);
    params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());
    params.put("ip", instance.getIp());
    params.put("port", String.valueOf(instance.getPort()));
    params.put("weight", String.valueOf(instance.getWeight()));
    params.put("enable", String.valueOf(instance.isEnabled()));
    params.put("healthy", String.valueOf(instance.isHealthy()));
    params.put("ephemeral", String.valueOf(instance.isEphemeral()));
    params.put("metadata", JacksonUtils.toJson(instance.getMetadata()));

    //发送http请求
    reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.POST);

}

reqApi方法将客户端的信息如:ip,端口,命名空间等信息,发送给服务端,进行注册。

在这里插入图片描述

点进方法

/**
 * Request api.
 *
 * @param api     api
 * @param params  parameters
 * @param body    body
 * @param servers servers
 * @param method  http method
 * @return result
 * @throws NacosException nacos exception
 */
public String reqApi(String api, Map<String, String> params, Map<String, String> body, List<String> servers,
        String method) throws NacosException {

    params.put(CommonParams.NAMESPACE_ID, getNamespaceId());

    if (CollectionUtils.isEmpty(servers) && StringUtils.isBlank(nacosDomain)) {
        throw new NacosException(NacosException.INVALID_PARAM, "no server available");
    }

    NacosException exception = new NacosException();

    if (StringUtils.isNotBlank(nacosDomain)) {
        for (int i = 0; i < maxRetry; i++) {
            try {
                //关键代码
                return callServer(api, params, body, nacosDomain, method);
            } catch (NacosException e) {
                exception = e;
                if (NAMING_LOGGER.isDebugEnabled()) {
                    NAMING_LOGGER.debug("request {} failed.", nacosDomain, e);
                }
            }
        }
    } else {
        Random random = new Random(System.currentTimeMillis());
        int index = random.nextInt(servers.size());

        for (int i = 0; i < servers.size(); i++) {
            String server = servers.get(index);
            try {
                return callServer(api, params, body, server, method);
            } catch (NacosException e) {
                exception = e;
                if (NAMING_LOGGER.isDebugEnabled()) {
                    NAMING_LOGGER.debug("request {} failed.", server, e);
                }
            }
            index = (index + 1) % servers.size();
        }
    }
    ...省略无关代码
}

进入callServer方法

/**
 * Call server.
 *
 * @param api       api
 * @param params    parameters
 * @param body      body
 * @param curServer ?
 * @param method    http method
 * @return result
 * @throws NacosException nacos exception
 */
public String callServer(String api, Map<String, String> params, Map<String, String> body, String curServer,
        String method) throws NacosException {
    long start = System.currentTimeMillis();
    long end = 0;
    injectSecurityInfo(params);
    Header header = builderHeader();

    String url;
    if (curServer.startsWith(UtilAndComs.HTTPS) || curServer.startsWith(UtilAndComs.HTTP)) {
        url = curServer + api;
    } else {
        if (!IPUtil.containsPort(curServer)) {
            curServer = curServer + IPUtil.IP_PORT_SPLITER + serverPort;
        }
        url = NamingHttpClientManager.getInstance().getPrefix() + curServer + api;
    }

    try {
        //发送请求
        HttpRestResult<String> restResult = nacosRestTemplate
                .exchangeForm(url, header, Query.newInstance().initParams(params), body, method, String.class);
        end = System.currentTimeMillis();

        MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(restResult.getCode()))
                .observe(end - start);

        if (restResult.ok()) {
            return restResult.getData();
        }
        if (HttpStatus.SC_NOT_MODIFIED == restResult.getCode()) {
            return StringUtils.EMPTY;
        }
        throw new NacosException(restResult.getCode(), restResult.getMessage());
    } catch (Exception e) {
        NAMING_LOGGER.error("[NA] failed to request", e);
        throw new NacosException(NacosException.SERVER_ERROR, e);
    }
}

url=http://localhost:8848/nacos/v1/ns/instance, 在nacos的OpenApi里,nacos/v1/ns/instance注册一个实例。

在这里插入图片描述

请求完成,控制台打印

INFO 18100 — [ main] c.a.c.n.registry.NacosServiceRegistry : nacos registry, stock-service 192.168.50.207:9002 register finished

总结

客户端代码启动是boot的自动加载机制+spring的事件通知。注册服务端动作就是发送一个url为v1/ns/instance的http请求给服务端。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值