经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
对dubbo的DubboReference.check的参数进行剖析
来源:cnblogs  作者:eaglelihh  时间:2023/4/24 8:57:41  对本文有异议

背景

在使用dubbo的时候,发现当消费者启动的时候,如果提供者没有启动,即使提供者后来启动了,消费者也调不通提供者提供的接口了。

注册中心使用都是nacos

dubbo版本是3.0.4

例子

接口

  1. public interface DemoService {
  2. String sayHello();
  3. }

提供者

  1. @DubboService
  2. public class DemoServiceImpl implements DemoService {
  3. @Override
  4. public String sayHello() {
  5. return "hello";
  6. }
  7. }
  8. @EnableDubbo
  9. @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
  10. public class ReferenceCheckProviderStarter {
  11. public static void main(String[] args) {
  12. new SpringApplicationBuilder(ReferenceCheckProviderStarter.class)
  13. .web(WebApplicationType.NONE) // .REACTIVE, .SERVLET
  14. .run(args);
  15. System.out.println("dubbo service started");
  16. }
  17. }

消费者

  1. @EnableDubbo
  2. @RestController
  3. @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
  4. public class ReferenceCheckConsumerStarter {
  5. @DubboReference
  6. private DemoService demoService;
  7. @GetMapping("/dubbo/nacos/test")
  8. public Object test() {
  9. return demoService.sayHello();
  10. }
  11. public static void main(String[] args) {
  12. SpringApplication.run(ReferenceCheckConsumerStarter.class, args);
  13. }
  14. }

1. 先启动provider,再启动consumer

a. 启动provider

nacos出现provider的服务

b. 启动consumer

nacos出现consumer的服务

  1. 访问 http://127.0.0.1:8080/dubbo/nacos/test 后返回
  2. hello

c. 终止provider

nacos上provider的服务消失了

  1. 访问 http://127.0.0.1:8080/dubbo/nacos/test 后返回
  2. No provider available from registry

d. 重新启动provider

nacos出现provider的服务

  1. 访问 http://127.0.0.1:8080/dubbo/nacos/test 后返回
  2. hello

可以看出:先启动provider,再启动consumer,整个过程是没问题。

2. 先启动consumer,再启动provider

a. 启动consumer


nacos出现consumer的服务,但立即又消失了

b. 启动provider

nacos出现provider的服务

  1. 访问 http://127.0.0.1:8080/dubbo/nacos/test 后返回
  2. Directory already destroyed .

可以看出:当consumer先启动时,如果provider此时没有启动,consumer就再也访问不到provider的服务了。

3. 先启动consumer,再启动provider (check=false)

修改一下注解@DubboRefere的参数

  1. @DubboReference(check = false)
  2. private DemoService demoService;

a. 启动consumer

nacos出现consumer的服务

  1. 访问 http://127.0.0.1:8080/dubbo/nacos/test 后返回
  2. No provider available from registry

b. 启动provider

nacos出现provider的服务

  1. 访问 http://127.0.0.1:8080/dubbo/nacos/test 后返回
  2. hello

可以看出:即使是consumer先启动,当provider启动后,consumer还是能够访问到provider的服务的。

关于报错

org.apache.dubbo.rpc.RpcException: No provider available from registry

  1. public class RegistryDirectory<T> extends DynamicDirectory<T> {
  2. @Override
  3. public List<Invoker<T>> doList(Invocation invocation) {
  4. if (forbidden) {
  5. // 1. No service provider 2. Service providers are disabled
  6. throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "No provider available from registry " +
  7. getUrl().getAddress() + " for service " + getConsumerUrl().getServiceKey() + " on consumer " +
  8. NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() +
  9. ", please check status of providers(disabled, not registered or in blacklist).");
  10. }
  11. // ......
  12. }
  13. }
  1. public class ServiceDiscoveryRegistryDirectory<T> extends DynamicDirectory<T> {
  2. String EMPTY_PROTOCOL = "empty";
  3. private void refreshInvoker(List<URL> invokerUrls) {
  4. Assert.notNull(invokerUrls, "invokerUrls should not be null, use empty url list to clear address.");
  5. this.originalUrls = invokerUrls;
  6. if (invokerUrls.size() == 0) {
  7. logger.info("Received empty url list...");
  8. this.forbidden = true; // Forbid to access // 这里
  9. this.invokers = Collections.emptyList();
  10. routerChain.setInvokers(this.invokers);
  11. destroyAllInvokers(); // Close all invokers
  12. } else {
  13. this.forbidden = false; // Allow accessing // 这里
  14. if (CollectionUtils.isEmpty(invokerUrls)) {
  15. return;
  16. }
  17. // can't use local reference because this.urlInvokerMap might be accessed at isAvailable() by main thread concurrently.
  18. Map<String, Invoker<T>> oldUrlInvokerMap = null;
  19. if (this.urlInvokerMap != null) {
  20. // the initial capacity should be set greater than the maximum number of entries divided by the load factor to avoid resizing.
  21. oldUrlInvokerMap = new LinkedHashMap<>(Math.round(1 + this.urlInvokerMap.size() / DEFAULT_HASHMAP_LOAD_FACTOR));
  22. this.urlInvokerMap.forEach(oldUrlInvokerMap::put);
  23. }
  24. Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(oldUrlInvokerMap, invokerUrls);// Translate url list to Invoker map // 这里
  25. logger.info("Refreshed invoker size " + newUrlInvokerMap.size());
  26. if (CollectionUtils.isEmptyMap(newUrlInvokerMap)) {
  27. logger.error(new IllegalStateException("Cannot create invokers from url address list (total " + invokerUrls.size() + ")"));
  28. return;
  29. }
  30. List<Invoker<T>> newInvokers = Collections.unmodifiableList(new ArrayList<>(newUrlInvokerMap.values()));
  31. // pre-route and build cache, notice that route cache should build on original Invoker list.
  32. // toMergeMethodInvokerMap() will wrap some invokers having different groups, those wrapped invokers not should be routed.
  33. routerChain.setInvokers(newInvokers);
  34. this.invokers = multiGroup ? toMergeInvokerList(newInvokers) : newInvokers;
  35. this.urlInvokerMap = newUrlInvokerMap; // 这里
  36. if (oldUrlInvokerMap != null) {
  37. try {
  38. destroyUnusedInvokers(oldUrlInvokerMap, newUrlInvokerMap); // Close the unused Invoker
  39. } catch (Exception e) {
  40. logger.warn("destroyUnusedInvokers error. ", e);
  41. }
  42. }
  43. }
  44. // notify invokers refreshed
  45. this.invokersChanged();
  46. }
  47. private synchronized void refreshOverrideAndInvoker(List<URL> instanceUrls) {
  48. // mock zookeeper://xxx?mock=return null
  49. if (enableConfigurationListen) {
  50. overrideDirectoryUrl();
  51. }
  52. refreshInvoker(instanceUrls); // 这里
  53. }
  54. }
  1. public class RegistryDirectory<T> extends DynamicDirectory<T> {
  2. @Override
  3. public synchronized void notify(List<URL> urls) {
  4. if (isDestroyed()) {
  5. return;
  6. }
  7. Map<String, List<URL>> categoryUrls = urls.stream()
  8. .filter(Objects::nonNull)
  9. .filter(this::isValidCategory)
  10. .filter(this::isNotCompatibleFor26x)
  11. .collect(Collectors.groupingBy(this::judgeCategory));
  12. List<URL> configuratorURLs = categoryUrls.getOrDefault(CONFIGURATORS_CATEGORY, Collections.emptyList());
  13. this.configurators = Configurator.toConfigurators(configuratorURLs).orElse(this.configurators);
  14. List<URL> routerURLs = categoryUrls.getOrDefault(ROUTERS_CATEGORY, Collections.emptyList());
  15. toRouters(routerURLs).ifPresent(this::addRouters);
  16. // providers
  17. List<URL> providerURLs = categoryUrls.getOrDefault(PROVIDERS_CATEGORY, Collections.emptyList());
  18. // 3.x added for extend URL address
  19. ExtensionLoader<AddressListener> addressListenerExtensionLoader = getUrl().getOrDefaultModuleModel().getExtensionLoader(AddressListener.class);
  20. List<AddressListener> supportedListeners = addressListenerExtensionLoader.getActivateExtension(getUrl(), (String[]) null);
  21. if (supportedListeners != null && !supportedListeners.isEmpty()) {
  22. for (AddressListener addressListener : supportedListeners) {
  23. providerURLs = addressListener.notify(providerURLs, getConsumerUrl(),this);
  24. }
  25. }
  26. refreshOverrideAndInvoker(providerURLs); // 这里
  27. }
  28. }
  29. public abstract class AbstractRegistry implements Registry {
  30. /**
  31. * Notify changes from the Provider side.
  32. *
  33. * @param url consumer side url
  34. * @param listener listener
  35. * @param urls provider latest urls
  36. */
  37. protected void notify(URL url, NotifyListener listener, List<URL> urls) {
  38. if (url == null) {
  39. throw new IllegalArgumentException("notify url == null");
  40. }
  41. if (listener == null) {
  42. throw new IllegalArgumentException("notify listener == null");
  43. }
  44. if ((CollectionUtils.isEmpty(urls))
  45. && !ANY_VALUE.equals(url.getServiceInterface())) {
  46. logger.warn("Ignore empty notify urls for subscribe url " + url);
  47. return;
  48. }
  49. if (logger.isInfoEnabled()) {
  50. logger.info("Notify urls for subscribe url " + url + ", url size: " + urls.size());
  51. }
  52. // keep every provider's category.
  53. Map<String, List<URL>> result = new HashMap<>(); // 这里
  54. for (URL u : urls) {
  55. if (UrlUtils.isMatch(url, u)) {
  56. String category = u.getCategory(DEFAULT_CATEGORY);
  57. List<URL> categoryList = result.computeIfAbsent(category, k -> new ArrayList<>()); // 这里
  58. categoryList.add(u); // 这里
  59. }
  60. }
  61. if (result.size() == 0) {
  62. return;
  63. }
  64. Map<String, List<URL>> categoryNotified = notified.computeIfAbsent(url, u -> new ConcurrentHashMap<>());
  65. for (Map.Entry<String, List<URL>> entry : result.entrySet()) {
  66. String category = entry.getKey();
  67. List<URL> categoryList = entry.getValue();
  68. categoryNotified.put(category, categoryList);
  69. listener.notify(categoryList); // 这里
  70. // We will update our cache file after each notification.
  71. // When our Registry has a subscribe failure due to network jitter, we can return at least the existing cache URL.
  72. if (localCacheEnabled) {
  73. saveProperties(url);
  74. }
  75. }
  76. }
  77. }
  1. public class NacosRegistry extends FailbackRegistry {
  2. private void notifySubscriber(URL url, NotifyListener listener, Collection<Instance> instances) {
  3. List<Instance> enabledInstances = new LinkedList<>(instances);
  4. if (enabledInstances.size() > 0) {
  5. // Instances
  6. filterEnabledInstances(enabledInstances);
  7. }
  8. List<URL> urls = toUrlWithEmpty(url, enabledInstances);
  9. NacosRegistry.this.notify(url, listener, urls); // 这里
  10. }
  11. String EMPTY_PROTOCOL = "empty";
  12. private List<URL> toUrlWithEmpty(URL consumerURL, Collection<Instance> instances) {
  13. List<URL> urls = buildURLs(consumerURL, instances);
  14. if (urls.size() == 0) { // 这里
  15. URL empty = URLBuilder.from(consumerURL)
  16. .setProtocol(EMPTY_PROTOCOL)
  17. .addParameter(CATEGORY_KEY, DEFAULT_CATEGORY)
  18. .build();
  19. urls.add(empty);
  20. }
  21. return urls;
  22. }
  23. }

当没有可用的服务时,instances是空的

当有可用的服务时,instances是不为空的

是怎么通知的

  1. public class ServiceInfoHolder implements Closeable {
  2. public ServiceInfo processServiceInfo(ServiceInfo serviceInfo) {
  3. String serviceKey = serviceInfo.getKey();
  4. if (serviceKey == null) {
  5. return null;
  6. }
  7. ServiceInfo oldService = serviceInfoMap.get(serviceInfo.getKey());
  8. if (isEmptyOrErrorPush(serviceInfo)) {
  9. //empty or error push, just ignore
  10. return oldService;
  11. }
  12. serviceInfoMap.put(serviceInfo.getKey(), serviceInfo);
  13. boolean changed = isChangedServiceInfo(oldService, serviceInfo);
  14. if (StringUtils.isBlank(serviceInfo.getJsonFromServer())) {
  15. serviceInfo.setJsonFromServer(JacksonUtils.toJson(serviceInfo));
  16. }
  17. MetricsMonitor.getServiceInfoMapSizeMonitor().set(serviceInfoMap.size());
  18. if (changed) { // 这里
  19. NAMING_LOGGER.info("current ips:(" + serviceInfo.ipCount() + ") service: " + serviceInfo.getKey() + " -> "
  20. + JacksonUtils.toJson(serviceInfo.getHosts()));
  21. NotifyCenter.publishEvent(new InstancesChangeEvent(serviceInfo.getName(), serviceInfo.getGroupName(),
  22. serviceInfo.getClusters(), serviceInfo.getHosts())); // 这里
  23. DiskCache.write(serviceInfo, cacheDir);
  24. }
  25. return serviceInfo;
  26. }
  27. }
  28. public class DefaultPublisher extends Thread implements EventPublisher {
  29. private BlockingQueue<Event> queue;
  30. @Override
  31. public void init(Class<? extends Event> type, int bufferSize) {
  32. setDaemon(true);
  33. setName("nacos.publisher-" + type.getName());
  34. this.eventType = type;
  35. this.queueMaxSize = bufferSize;
  36. this.queue = new ArrayBlockingQueue<>(bufferSize); // 这里
  37. start();
  38. }
  39. @Override
  40. public boolean publish(Event event) {
  41. checkIsStart();
  42. boolean success = this.queue.offer(event); // 这里
  43. if (!success) {
  44. LOGGER.warn("Unable to plug in due to interruption, synchronize sending time, event : {}", event);
  45. receiveEvent(event);
  46. return true;
  47. }
  48. return true;
  49. }
  50. @Override
  51. public void run() {
  52. openEventHandler();
  53. }
  54. void openEventHandler() {
  55. try {
  56. // This variable is defined to resolve the problem which message overstock in the queue.
  57. int waitTimes = 60;
  58. // To ensure that messages are not lost, enable EventHandler when
  59. // waiting for the first Subscriber to register
  60. for (; ; ) {
  61. if (shutdown || hasSubscriber() || waitTimes <= 0) {
  62. break;
  63. }
  64. ThreadUtils.sleep(1000L);
  65. waitTimes--;
  66. }
  67. for (; ; ) {
  68. if (shutdown) {
  69. break;
  70. }
  71. final Event event = queue.take(); // 这里
  72. receiveEvent(event); // 这里
  73. UPDATER.compareAndSet(this, lastEventSequence, Math.max(lastEventSequence, event.sequence()));
  74. }
  75. } catch (Throwable ex) {
  76. LOGGER.error("Event listener exception : ", ex);
  77. }
  78. }
  79. void receiveEvent(Event event) {
  80. final long currentEventSequence = event.sequence();
  81. if (!hasSubscriber()) {
  82. LOGGER.warn("[NotifyCenter] the {} is lost, because there is no subscriber.");
  83. return;
  84. }
  85. // Notification single event listener
  86. for (Subscriber subscriber : subscribers) {
  87. // Whether to ignore expiration events
  88. if (subscriber.ignoreExpireEvent() && lastEventSequence > currentEventSequence) {
  89. LOGGER.debug("[NotifyCenter] the {} is unacceptable to this subscriber, because had expire",
  90. event.getClass());
  91. continue;
  92. }
  93. // Because unifying smartSubscriber and subscriber, so here need to think of compatibility.
  94. // Remove original judge part of codes.
  95. notifySubscriber(subscriber, event); // 这里
  96. }
  97. }
  98. @Override
  99. public void notifySubscriber(final Subscriber subscriber, final Event event) {
  100. LOGGER.debug("[NotifyCenter] the {} will received by {}", event, subscriber);
  101. final Runnable job = () -> subscriber.onEvent(event);
  102. final Executor executor = subscriber.executor();
  103. if (executor != null) {
  104. executor.execute(job); // 这里
  105. } else {
  106. try {
  107. job.run(); // 这里
  108. } catch (Throwable e) {
  109. LOGGER.error("Event callback exception: ", e);
  110. }
  111. }
  112. }
  113. }
  114. public class InstancesChangeNotifier extends Subscriber<InstancesChangeEvent> {
  115. @Override
  116. public void onEvent(InstancesChangeEvent event) {
  117. String key = ServiceInfo
  118. .getKey(NamingUtils.getGroupedName(event.getServiceName(), event.getGroupName()), event.getClusters());
  119. ConcurrentHashSet<EventListener> eventListeners = listenerMap.get(key);
  120. if (CollectionUtils.isEmpty(eventListeners)) {
  121. return;
  122. }
  123. for (final EventListener listener : eventListeners) {
  124. final com.alibaba.nacos.api.naming.listener.Event namingEvent = transferToNamingEvent(event);
  125. if (listener instanceof AbstractEventListener && ((AbstractEventListener) listener).getExecutor() != null) {
  126. ((AbstractEventListener) listener).getExecutor().execute(() -> listener.onEvent(namingEvent)); // 这里
  127. } else {
  128. listener.onEvent(namingEvent); // 这里
  129. }
  130. }
  131. }
  132. }
  133. public class NacosRegistry extends FailbackRegistry {
  134. @Override
  135. public void onEvent(Event event) {
  136. if (event instanceof NamingEvent) {
  137. NamingEvent e = (NamingEvent) event;
  138. notifier.notify(e.getInstances()); // 这里
  139. }
  140. }
  141. }
  142. public abstract class RegistryNotifier {
  143. public synchronized void notify(Object rawAddresses) {
  144. this.rawAddresses = rawAddresses;
  145. long notifyTime = System.currentTimeMillis();
  146. this.lastEventTime = notifyTime;
  147. long delta = (System.currentTimeMillis() - lastExecuteTime) - delayTime;
  148. // more than 10 calls && next execute time is in the future
  149. boolean delay = shouldDelay.get() && delta < 0;
  150. if (delay) {
  151. scheduler.schedule(new NotificationTask(this, notifyTime), -delta, TimeUnit.MILLISECONDS); // 这里
  152. } else {
  153. // check if more than 10 calls
  154. if (!shouldDelay.get() && executeTime.incrementAndGet() > DEFAULT_DELAY_EXECUTE_TIMES) {
  155. shouldDelay.set(true);
  156. }
  157. scheduler.submit(new NotificationTask(this, notifyTime)); // 这里
  158. }
  159. }
  160. public static class NotificationTask implements Runnable {
  161. private final RegistryNotifier listener;
  162. private final long time;
  163. public NotificationTask(RegistryNotifier listener, long time) {
  164. this.listener = listener;
  165. this.time = time;
  166. }
  167. @Override
  168. public void run() {
  169. try {
  170. if (this.time == listener.lastEventTime) {
  171. listener.doNotify(listener.rawAddresses); // 这里
  172. listener.lastExecuteTime = System.currentTimeMillis();
  173. synchronized (listener) {
  174. if (this.time == listener.lastEventTime) {
  175. listener.rawAddresses = null;
  176. }
  177. }
  178. }
  179. } catch (Throwable t) {
  180. logger.error("Error occurred when notify directory. ", t);
  181. }
  182. }
  183. }}
  184. }
  185. public class NacosRegistry extends FailbackRegistry {
  186. private class RegistryChildListenerImpl implements EventListener {
  187. private RegistryNotifier notifier;
  188. public RegistryChildListenerImpl(String serviceName, URL consumerUrl, NotifyListener listener) {
  189. notifier = new RegistryNotifier(getUrl(), NacosRegistry.this.getDelay()) {
  190. @Override
  191. protected void doNotify(Object rawAddresses) {
  192. List<Instance> instances = (List<Instance>) rawAddresses;
  193. if (isServiceNamesWithCompatibleMode(consumerUrl)) {
  194. /**
  195. * Get all instances with corresponding serviceNames to avoid instance overwrite and but with empty instance mentioned
  196. * in https://github.com/apache/dubbo/issues/5885 and https://github.com/apache/dubbo/issues/5899
  197. */
  198. NacosInstanceManageUtil.initOrRefreshServiceInstanceList(serviceName, instances);
  199. instances = NacosInstanceManageUtil.getAllCorrespondingServiceInstanceList(serviceName);
  200. }
  201. NacosRegistry.this.notifySubscriber(consumerUrl, listener, instances); // 这里
  202. }
  203. };
  204. }
  205. }

然后就调用了上面的????

什么时候添加监听器的?

  1. public class NacosRegistry extends FailbackRegistry {
  2. private void subscribeEventListener(String serviceName, final URL url, final NotifyListener listener)
  3. throws NacosException {
  4. EventListener eventListener = new RegistryChildListenerImpl(serviceName, url, listener); // 这里
  5. namingService.subscribe(serviceName,
  6. getUrl().getGroup(Constants.DEFAULT_GROUP),
  7. eventListener); // 这里
  8. }
  9. private void doSubscribe(final URL url, final NotifyListener listener, final Set<String> serviceNames) {
  10. try {
  11. if (isServiceNamesWithCompatibleMode(url)) {
  12. List<Instance> allCorrespondingInstanceList = Lists.newArrayList();
  13. /**
  14. * Get all instances with serviceNames to avoid instance overwrite and but with empty instance mentioned
  15. * in https://github.com/apache/dubbo/issues/5885 and https://github.com/apache/dubbo/issues/5899
  16. *
  17. * namingService.getAllInstances with {@link org.apache.dubbo.registry.support.AbstractRegistry#registryUrl}
  18. * default {@link DEFAULT_GROUP}
  19. *
  20. * in https://github.com/apache/dubbo/issues/5978
  21. */
  22. for (String serviceName : serviceNames) {
  23. List<Instance> instances = namingService.getAllInstances(serviceName,
  24. getUrl().getGroup(Constants.DEFAULT_GROUP));
  25. NacosInstanceManageUtil.initOrRefreshServiceInstanceList(serviceName, instances);
  26. allCorrespondingInstanceList.addAll(instances);
  27. }
  28. notifySubscriber(url, listener, allCorrespondingInstanceList);
  29. for (String serviceName : serviceNames) {
  30. subscribeEventListener(serviceName, url, listener); // 这里
  31. }
  32. } else {
  33. for (String serviceName : serviceNames) {
  34. List<Instance> instances = new LinkedList<>();
  35. instances.addAll(namingService.getAllInstances(serviceName
  36. , getUrl().getGroup(Constants.DEFAULT_GROUP)));
  37. String serviceInterface = serviceName;
  38. String[] segments = serviceName.split(SERVICE_NAME_SEPARATOR, -1);
  39. if (segments.length == 4) {
  40. serviceInterface = segments[SERVICE_INTERFACE_INDEX];
  41. }
  42. URL subscriberURL = url.setPath(serviceInterface).addParameters(INTERFACE_KEY, serviceInterface,
  43. CHECK_KEY, String.valueOf(false));
  44. notifySubscriber(subscriberURL, listener, instances);
  45. subscribeEventListener(serviceName, subscriberURL, listener);
  46. }
  47. }
  48. } catch (Throwable cause) {
  49. throw new RpcException("Failed to subscribe " + url + " to nacos " + getUrl() + ", cause: " + cause.getMessage(), cause);
  50. }
  51. }
  52. }

org.apache.dubbo.rpc.RpcException: Directory already destroyed

  1. public abstract class AbstractDirectory<T> implements Directory<T> {
  2. @Override
  3. public List<Invoker<T>> list(Invocation invocation) throws RpcException {
  4. if (destroyed) {
  5. throw new RpcException("Directory already destroyed .url: " + getUrl());
  6. }
  7. return doList(invocation);
  8. }
  9. @Override
  10. public void destroy() {
  11. destroyed = true; // 这里
  12. }
  13. }
  1. public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
  2. private void checkInvokerAvailable() throws IllegalStateException {
  3. if (shouldCheck() && !invoker.isAvailable()) {
  4. invoker.destroy(); // 这里
  5. throw new IllegalStateException("Should has at least one way to know which services this interface belongs to," +
  6. " subscription url: " + invoker.getUrl());
  7. }
  8. }
  9. protected synchronized void init() {
  10. // ......
  11. checkInvokerAvailable(); // 这里
  12. }
  13. }
  1. public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
  2. public boolean shouldCheck() {
  3. checkDefault();
  4. Boolean shouldCheck = isCheck(); // 这里
  5. if (shouldCheck == null && getConsumer() != null) {
  6. shouldCheck = getConsumer().isCheck();
  7. }
  8. if (shouldCheck == null) {
  9. // default true // 这里
  10. shouldCheck = true;
  11. }
  12. return shouldCheck;
  13. }
  14. }
  1. public class RegistryDirectory<T> extends DynamicDirectory<T> {
  2. @Override
  3. public boolean isAvailable() {
  4. if (isDestroyed() || this.forbidden) { // 这里
  5. return false;
  6. }
  7. Map<URL, Invoker<T>> localUrlInvokerMap = urlInvokerMap; // 这里
  8. return CollectionUtils.isNotEmptyMap(localUrlInvokerMap)
  9. && localUrlInvokerMap.values().stream().anyMatch(Invoker::isAvailable);
  10. }
  11. }

如果没有设置check字段,那么就会在启动的时候检查提供方是否可用,如果不可用,就销毁了。

原文链接:https://www.cnblogs.com/eaglelihh/p/17339915.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号