
这是在真正调用注册实例的方法之前,需要使用到的对象的关系图。
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",matchIfMissing = true)
@AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class,AutoServiceRegistrationAutoConfiguration.class,NacosDiscoveryAutoConfiguration.class })
public class NacosServiceRegistryAutoConfiguration {@Beanpublic NacosServiceRegistry nacosServiceRegistry(// 在spring.factories中,有个自动创建的类是 NacosServiceAutoConfiguration,这个类里创建了 NacosServiceManager 对象,也就是对应这里的第一个参数NacosServiceManager nacosServiceManager, NacosDiscoveryProperties nacosDiscoveryProperties) { // 取的配置文件return new NacosServiceRegistry(nacosServiceManager, nacosDiscoveryProperties);}@Bean@ConditionalOnBean(AutoServiceRegistrationProperties.class)public NacosRegistration nacosRegistration(ObjectProvider> registrationCustomizers, // 不知道是个啥,感觉不是重点所以没看NacosDiscoveryProperties nacosDiscoveryProperties, // 配置文件ApplicationContext context) { // spring容器创建的return new NacosRegistration(registrationCustomizers.getIfAvailable(),nacosDiscoveryProperties, context);}@Bean@ConditionalOnBean(AutoServiceRegistrationProperties.class)这个是才是重点对象public NacosAutoServiceRegistration nacosAutoServiceRegistration(NacosServiceRegistry registry, // 上面第一个方法创建的BeanAutoServiceRegistrationProperties autoServiceRegistrationProperties, // 取的配置文件中的值NacosRegistration registration) { // 上面第二个方法创建的Beanreturn new NacosAutoServiceRegistration(registry,autoServiceRegistrationProperties, registration);}}
直接看NacosAutoServiceRegistration继承的这个抽象类
@Override@SuppressWarnings("deprecation")// NacosAutoServiceRegistration类有实现ApplicationListener,所以会监听到WebServerInitializedEvent事件public void onApplicationEvent(WebServerInitializedEvent event) {bind(event);}public void bind(WebServerInitializedEvent event) {ApplicationContext context = event.getApplicationContext();if (context instanceof ConfigurableWebServerApplicationContext) {if ("management".equals(((ConfigurableWebServerApplicationContext) context).getServerNamespace())) {return;}}this.port.compareAndSet(0, event.getWebServer().getPort());this.start();}public void start() {if (!isEnabled()) {if (logger.isDebugEnabled()) {logger.debug("Discovery Lifecycle disabled. Not starting");}return;}if (!this.running.get()) {// NacosServiceManager类中的 onInstancePreRegisteredEvent 方法上有@EventListener,会监听到这个预注册事件,具体不知道逻辑,看变量名称好像缓存 用的this.context.publishEvent(new InstancePreRegisteredEvent(this, getRegistration()));// 会调用register方法register();if (shouldRegisterManagement()) {registerManagement();}this.context.publishEvent(new InstanceRegisteredEvent<>(this, getConfiguration()));this.running.compareAndSet(false, true);}}
一直溯源register方法,会看到NacosServiceRegistry类中的register(Registration registration)方法,
@Overridepublic void register(Registration registration) {if (StringUtils.isEmpty(registration.getServiceId())) {log.warn("No service to register for nacos client...");return;}// 这里的namingService()溯源会看到创建这个NamingService 用到了反射NamingService namingService = namingService();// serviceId 其实就是spring.application.name值String serviceId = registration.getServiceId();String group = nacosDiscoveryProperties.getGroup();// 直接new一个Instance对象Instance instance = getNacosInstanceFromRegistration(registration);try {namingService.registerInstance(serviceId, group, instance);log.info("nacos registry, {} {} {}:{} register finished", group, serviceId,instance.getIp(), instance.getPort());}catch (Exception e) {if (nacosDiscoveryProperties.isFailFast()) {log.error("nacos registry, {} register failed...{},", serviceId,registration.toString(), e);rethrowRuntimeException(e);}else {log.warn("Failfast is false. {} register failed...{},", serviceId,registration.toString(), e);}}}
创建NamingService的具体代码:
public static NamingService createNamingService(Properties properties) throws NacosException {try {Class> driverImplClass = Class.forName("com.alibaba.nacos.client.naming.NacosNamingService");Constructor constructor = driverImplClass.getConstructor(Properties.class);NamingService vendorImpl = (NamingService)constructor.newInstance(properties);return vendorImpl;} catch (Throwable var4) {throw new NacosException(-400, var4);}}
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {// 这里校验的就是配置的心跳间隔和心跳超时,ip删除超时三个参数的值的大小关系,心跳间隔必须比这两个都要小NamingUtils.checkInstanceIsLegal(instance);String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);// 如果是临时实例,就会开一个心跳线程,不设置事件默认应该是5s的延迟if (instance.isEphemeral()) {BeatInfo beatInfo = this.beatReactor.buildBeatInfo(groupedServiceName, instance);this.beatReactor.addBeatInfo(groupedServiceName, beatInfo);}this.serverProxy.registerService(groupedServiceName, groupName, instance);}
public String callServer(String api, Map params, Map body, String curServer, String method) throws NacosException {long start = System.currentTimeMillis();long end = 0L;this.injectSecurityInfo(params);Header header = this.builderHeader();String url;if (!curServer.startsWith("https://") && !curServer.startsWith("http://")) {if (!IPUtil.containsPort(curServer)) {curServer = curServer + ":" + this.serverPort;}url = NamingHttpClientManager.getInstance().getPrefix() + curServer + api;} else {url = curServer + api;}try {// 这里的nacosRestTemplate 点进去溯源之后会发现 HttpRestResult restResult = this.nacosRestTemplate.exchangeForm(url, header, Query.newInstance().initParams(params), body, method, String.class);end = System.currentTimeMillis();MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(restResult.getCode())).observe((double)(end - start));if (restResult.ok()) {return (String)restResult.getData();} else if (304 == restResult.getCode()) {return "";} else {throw new NacosException(restResult.getCode(), restResult.getMessage());}} catch (Exception var13) {LogUtils.NAMING_LOGGER.error("[NA] failed to request", var13);throw new NacosException(500, var13);}}
// 先是在NamingProxy中显式创建NacosRestTemplate 对象
private final NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getInstance().getNacosRestTemplate();NamingHttpClientManager类// 这里传入的参数其实是NamingHttpClientFactory对象,并且这个对象是继承了AbstractHttpClientFactory抽象类的public NacosRestTemplate getNacosRestTemplate() {return HttpClientBeanHolder.getNacosRestTemplate(HTTP_CLIENT_FACTORY);}HttpClientBeanHolder类public static NacosRestTemplate getNacosRestTemplate(HttpClientFactory httpClientFactory) {if (httpClientFactory == null) {throw new NullPointerException("httpClientFactory is null");}String factoryName = httpClientFactory.getClass().getName();NacosRestTemplate nacosRestTemplate = SINGLETON_REST.get(factoryName);if (nacosRestTemplate == null) {synchronized (SINGLETON_REST) {nacosRestTemplate = SINGLETON_REST.get(factoryName);if (nacosRestTemplate != null) {return nacosRestTemplate;}// 如果SINGLETON_REST 这个集合中没有找到,会走到这个方法,会发现 参数传过来的 httpClientFactory是个接口,并且有两个实现类,分别是AbstractApacheHttpClientFactory和AbstractHttpClientFactory,因为知道入参其实就是NamingHttpClientFactory,并且继承了AbstractHttpClientFactorynacosRestTemplate = httpClientFactory.createNacosRestTemplate();SINGLETON_REST.put(factoryName, nacosRestTemplate);}}return nacosRestTemplate;}AbstractHttpClientFactory类HttpClientConfig httpClientConfig = buildHttpClientConfig();// 这里就知道NacosRestTemplate中的HttpClientRequest属性其实是 JdkHttpClientRequest实例对象,final JdkHttpClientRequest clientRequest = new JdkHttpClientRequest(httpClientConfig);// enable sslinitTls(new BiConsumer() {@Overridepublic void accept(SSLContext sslContext, HostnameVerifier hostnameVerifier) {clientRequest.setSSLContext(loadSSLContext());clientRequest.replaceSSLHostnameVerifier(hostnameVerifier);}}, new TlsFileWatcher.FileChangeListener() {@Overridepublic void onChanged(String filePath) {clientRequest.setSSLContext(loadSSLContext());}});return new NacosRestTemplate(assignLogger(), clientRequest);}
在上面NamingProxy中一顿点击之后,会调用到NacosRestTemplate的execute方法,如下
private HttpRestResult execute(String url, String httpMethod, RequestHttpEntity requestEntity,Type responseType) throws Exception {URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());if (logger.isDebugEnabled()) {logger.debug("HTTP method: {}, url: {}, body: {}", httpMethod, uri, requestEntity.getBody());}ResponseHandler responseHandler = super.selectResponseHandler(responseType);HttpClientResponse response = null;try {/// 上面溯源得到的 JdkHttpClientRequest 对应的就是this.requestClient(),因为上面可以看到调用NacosRestTemplate的构造函数,传入的是JdkHttpClientRequest response = this.requestClient().execute(uri, httpMethod, requestEntity);return responseHandler.handle(response);} finally {if (response != null) {response.close();}}}
之后就是使用HttpURLConnection实际发情请求,并且处理Response了。
上一篇:暗无天日近反义词
下一篇:形容“加班”的古诗句