Dubbo-服务注册与发现机制
服务引用过程中涉及到服务发现机制
RegistryProtocol#doRefer
private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) { // 创建 RegistryDirectory 实例, 基于注册中心动态发现服务提供者(服务提供者新增或减少) RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url); // 设置注册中心和协议 directory.setRegistry(registry); directory.setProtocol(protocol); // 获取服务消费者的配置属性 Map<String, String> parameters = new HashMap<String, String>(directory.getConsumerUrl().getParameters()); // 生成服务消费者URL, 如: consumer://192.168.56.1/com.alibaba.dubbo.demo.DemoService?application=demo-consumer&check=false&dubbo=2.0.0&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=9892&qos.port=33333&side=consumer×tamp=1528380277185 URL subscribeUrl = new URL(CONSUMER_PROTOCOL, parameters.remove(REGISTER_IP_KEY), 0, type.getName(), parameters); // 注册服务消费者,在 consumers 目录下新节点 if (directory.isShouldRegister()) { directory.setRegisteredConsumerUrl(subscribeUrl); registry.register(directory.getRegisteredConsumerUrl()); } directory.buildRouterChain(subscribeUrl); // 添加了category=consumers属性 // consumer://192.168.56.1/com.alibaba.dubbo.demo.DemoService?application=demo-consumer&category=consumers&check=false&dubbo=2.0.0&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=9892&qos.port=33333&side=consumer×tamp=1528380277185 // 订阅 providers、configurators、routers 等节点数据,如Zookeeper的Node节点添加Watcher监听 // 向注册中心订阅该URL,关注该服务下的providers,configurators,routers发生变化时通知RegistryDirectory,以便及时发现服务提供者、配置、路由规则的变化 directory.subscribe(toSubscribeUrl(subscribeUrl)); // 一个注册中心可能有多个服务提供者,因此这里需要将多个服务提供者合并为一个,利用集群策略返回集群Invoker Invoker<T> invoker = cluster.join(directory); List<RegistryProtocolListener> listeners = findRegistryProtocolListeners(url); if (CollectionUtils.isEmpty(listeners)) { return invoker; } RegistryInvokerWrapper<T> registryInvokerWrapper = new RegistryInvokerWrapper<>(directory, cluster, invoker); for (RegistryProtocolListener listener : listeners) { listener.onRefer(this, registryInvokerWrapper); } return registryInvokerWrapper; }
RegistryDirectory构造器
public RegistryDirectory(Class<T> serviceType, URL url) { super(url); if (serviceType == null) { throw new IllegalArgumentException("service type is null."); } shouldRegister = !ANY_VALUE.equals(url.getServiceInterface()) && url.getParameter(REGISTER_KEY, true); shouldSimplified = url.getParameter(SIMPLIFIED_KEY, false); if (url.getServiceKey() == null || url.getServiceKey().length() == 0) { throw new IllegalArgumentException("registry serviceKey is null."); } this.serviceType = serviceType; // 获取注册中心URL的serviceKey:com.alibaba.dubbo.registry.RegistryService this.serviceKey = url.getServiceKey(); // 获取注册中心URL消费提供者的所有配置参数:从url属性的refer this.queryMap = StringUtils.parseQueryString(url.getParameterAndDecoded(REFER_KEY)); // 注册中心的URL,移除监控中心以及其他属性值,只保留消息消费者的配置属性 this.overrideDirectoryUrl = this.directoryUrl = turnRegistryUrlToConsumerUrl(url); String group = directoryUrl.getParameter(GROUP_KEY, ""); this.multiGroup = group != null && (ANY_VALUE.equals(group) || group.contains(",")); }