服務提供者服務暴露過程是,當服務提供者NettyServer啟動完成后,向ZK注冊訂閱的過程
服務消費者服務暴露過程是,創建代理對象的時候,注ZK注冊訂閱的過程

一、服務提供方
注冊服務:調用register方法,ZookeeperRegistry中的doRegister方法。zk節點上生成
providers節點的過程。
訂閱服務:調用subscribe方法,ZookeeperRegistry中的doSubscribe方法。zk節點上生成
configurators節點的過程。
public class RegistryProtocol implements Protocol { public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException { //export invoker // 啟動NettyServer服務 final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker); URL registryUrl = getRegistryUrl(originInvoker); //registry provider final Registry registry = getRegistry(originInvoker); final URL registedProviderUrl = getRegistedProviderUrl(originInvoker); //to judge to delay publish whether or not boolean register = registedProviderUrl.getParameter("register", true); ProviderConsumerRegTable.registerProvider(originInvoker, registryUrl, registedProviderUrl); // 《服務提供方》向注冊中心注冊服務 if (register) { register(registryUrl, registedProviderUrl); ProviderConsumerRegTable.getProviderWrapper(originInvoker).setReg(true); } // Subscribe the override data // FIXME When the provider subscribes, it will affect the scene : a certain JVM exposes the service and call the same service. // Because the subscribed is cached key with the name of the service, it causes the subscription information to cover. final URL overrideSubscribeUrl = getSubscribedOverrideUrl(registedProviderUrl); final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl, originInvoker); overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener); // 《服務提供方》訂閱服務 registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener); //Ensure that a new exporter instance is returned every time export return new Exporter<T>() { public Invoker<T> getInvoker() { return exporter.getInvoker(); } public void unexport() { try { exporter.unexport(); } catch (Throwable t) { logger.warn(t.getMessage(), t); } try { registry.unregister(registedProviderUrl); } catch (Throwable t) { logger.warn(t.getMessage(), t); } try { overrideListeners.remove(overrideSubscribeUrl); registry.unsubscribe(overrideSubscribeUrl, overrideSubscribeListener); } catch (Throwable t) { logger.warn(t.getMessage(), t); } } }; } }
二、服務消費方
注冊服務:調用register方法,ZookeeperRegistry中的doRegister方法。zk節點上生成
consumers節點的過程。
訂閱服務:調用subscribe方法,ZookeeperRegistry中的doSubscribe方法。zk節點上生成
routers節點的過程。
我們知道消費者在創建代理bean的時候(即調用createProxy方法時),需要得到一個調用者invoker對象。
private transient volatile Invoker<?> invoker; private T createProxy(Map<String, String> map) { // 省略若干代碼... if (isJvmRefer) { URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map); // 核心方法,拿到invoker對象 invoker = refprotocol.refer(interfaceClass, url); } else { // 省略若干代碼... if (urls.size() == 1) { // 核心方法,拿到invoker對象 // refprotocol為Protocol$Adpative對象 invoker = refprotocol.refer(interfaceClass, urls.get(0)); } else { // 省略若干代碼... } } // 核心方法create service proxy // 將下面這段代碼替換成 ProxyFactory$Adaptive 中 getProxy中的部分 return (T) proxyFactory.getProxy(invoker); }
調用RegistryProtocol中的refer方法
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException { url = url.setProtocol(url.getParameter(Constants.REGISTRY_KEY, Constants.DEFAULT_REGISTRY)).removeParameter(Constants.REGISTRY_KEY); Registry registry = registryFactory.getRegistry(url); if (RegistryService.class.equals(type)) { return proxyFactory.getInvoker((T) registry, type, url); } // group="a,b" or group="*" Map<String, String> qs = StringUtils.parseQueryString(url.getParameterAndDecoded(Constants.REFER_KEY)); String group = qs.get(Constants.GROUP_KEY); if (group != null && group.length() > 0) { if ((Constants.COMMA_SPLIT_PATTERN.split(group)).length > 1 || "*".equals(group)) { return doRefer(getMergeableCluster(), registry, type, url); } } return doRefer(cluster, registry, type, url); } private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) { RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url); directory.setRegistry(registry); directory.setProtocol(protocol); // all attributes of REFER_KEY Map<String, String> parameters = new HashMap<String, String>(directory.getUrl().getParameters()); URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, parameters.remove(Constants.REGISTER_IP_KEY), 0, type.getName(), parameters); if (!Constants.ANY_VALUE.equals(url.getServiceInterface()) && url.getParameter(Constants.REGISTER_KEY, true)) { // 《服務消費方》注冊服務 registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY, Constants.CHECK_KEY, String.valueOf(false))); } // 《服務消費方》訂閱服務 directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY + "," + Constants.CONFIGURATORS_CATEGORY + "," + Constants.ROUTERS_CATEGORY)); Invoker invoker = cluster.join(directory); ProviderConsumerRegTable.registerConsuemr(invoker, url, subscribeUrl, directory); return invoker; }