1 服务在发起远程调用前,还需要经过哪些环节?能画出流程图吗?
1.1 组装url
List
1.2 获取注册中心的服务
if (urls.size() ==1) {
// 单注册中心消费
invoker =refprotocol.refer(interfaceClass,urls.get(0));
} else {
List> invokers =new ArrayList>();
URLregistryURL=null;
for (URL url :urls) {
// 逐个获取注册中心的服务,并添加到invokers列表
invokers.add(refprotocol.refer(interfaceClass, url));
}
}
1.3 注册中心实例
// 创建具体注册中心实例
Registry registry =registryFactory.getRegistry(url);
1.4 底层连接通信,订阅zk节点,增加节点监听器
registry = createRegistry(url); (工厂模式,模板模式)
1.5 cluster
// 处理订阅数据,并通过Cluster合并多个Invoker
doRefer(cluster, registry, type, url);
1.6 注册消费信息,拉取服务列表
// 注册消费信息到注册中心
registry.register(registeredConsumerUrl);
// 订阅服务提供者,路由和动态配置(第一次发起订阅时会进行一次数据拉取操作,同时触发RegistryDirectory#notify)
directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
Constants.PROVIDERS_CATEGORY
+"," + Constants.CONFIGURATORS_CATEGORY
+"," + Constants.ROUTERS_CATEGORY));
// 通过Cluster合并invokers
Invoker invoker = cluster.join(directory);
2 理解Directory是如何管理Invoker的?重点关注RegistryDirectory的实现
2.1 StaticDirectory
2.2 RegistryDirectory
2.2.1 对Invoker 做merge
2.2.2 路由规则过滤
3 理解自定义路由是如何实现的?
根据路由规则,实现过滤invoker
invokers = router.route(invokers, getConsumerUrl(), invocation);
// copy list
routers = routers ==null ?new ArrayList() :new ArrayList(routers);
// append url router
String routerkey =url.getParameter(Constants.ROUTER_KEY);
if (routerkey !=null && routerkey.length() >0) {
RouterFactory routerFactory = ExtensionLoader.getExtensionLoader(RouterFactory.class).getExtension(routerkey);
routers.add(routerFactory.getRouter(url));
}
// append mock invoker selector
routers.add(new MockInvokersSelector());
routers.add(new TagRouter());
Collections.sort(routers);
this.routers = routers;