Motan refer 簡要處理流程
- 由AnnotationBean的postProcessBeforeInitialization方法開始
// 調用本類的私有方法refer
Object value = refer(reference, method.getParameterTypes()[0]);
// refer方法中調用RefererConfigBean父類的getRef方法
return referenceConfig.getRef();
- ReferenceConfig類(RefererConfigBean的父類)繼續處理
// getRef()只是做了個檢測,主要還在其調用的initRef方法中
// 先獲取 SimpleConfigHandler
ConfigHandler configHandler = ExtensionLoader.getExtensionLoader(ConfigHandler.class).getExtension(MotanConstants.DEFAULT_VALUE);
// 然后創建集群支持
ClusterSupport<T> clusterSupport = createClusterSupport(refUrl, configHandler, registryUrls);
// 最后通過configHandler完成refer操作
// 這里的proxy是代理方式,Motan好像只支持jdk的代理,所以proxy的值基本上就是 jdk了
ref = configHandler.refer(interfaceClass, clusters, proxy);
- 先看下createClusterSupport處理流程
// 對于createClusterSupport中一大片代碼為了獲取 regUrl,實際處理還是在configHandler中
return configHandler.buildClusterSupport(interfaceClass, regUrls);
// SimpleConfigHandler中的處理
public <T> ClusterSupport<T> buildClusterSupport(Class<T> interfaceClass, List<URL> registryUrls) {
// 創建集群支持類示例
ClusterSupport<T> clusterSupport = new ClusterSupport<T>(interfaceClass, registryUrls);
// 初始化
clusterSupport.init();
return clusterSupport;
}
// clusterSupport.init() 處理
// 先是獲取集群、負載均衡、HA策略,默認配置獲取的是:
// ClusterSpi ActiveWeightLoadBalance FailoverHaStrategy
prepareCluster();
// 獲取url motan://192.168.3.13:0/com.weibo.motan.demo.service.MotanDemoService?group=motan-demo-rpc
URL subUrl = toSubscribeUrl(url);
// 然后注冊
// client 注冊自己,同時訂閱service列表
// 這里是通過ZookeeperRegistryFactory獲取ZookeeperRegistry (Registry接口的實現類之一)
Registry registry = getRegistry(ru);
// 開始訂閱
registry.subscribe(subUrl, this);
- getRegistry(ru) 處理
// 獲取注冊url:zookeeper://127.0.0.1:2181/com.weibo.api.motan.registry.RegistryService
String registryUri = getRegistryUri(url);
// 如果不存在則通過ZookeeperRegistryFactory createRegistry來創建注冊中心
// 這里同時創建了ZkClient
ZkClient zkClient = new ZkClient(registryUrl.getParameter("address"), sessionTimeout, timeout);
// 創建并返回zk注冊中心
return new ZookeeperRegistry(registryUrl, zkClient);
// 創建注冊中心時,注冊狀態變化監聽事件
IZkStateListener zkStateListener = new IZkStateListener() {
@Override
public void handleStateChanged(Watcher.Event.KeeperState state) throws Exception {
// do nothing
}
@Override
public void handleNewSession() throws Exception {
LoggerUtil.info("zkRegistry get new session notify.");
reconnectService();
reconnectClient();
}
};
zkClient.subscribeStateChanges(zkStateListener);
- registry.subscribe(subUrl, this) 處理,主處理在CommandFailbackRegistry中
// url:motan://192.168.3.13:0/com.weibo.motan.demo.service.MotanDemoService?group=motan-demo-rpc
protected void doSubscribe(URL url, final NotifyListener listener) {
LoggerUtil.info("CommandFailbackRegistry subscribe. url: " + url.toSimpleString());
URL urlCopy = url.createCopy();
CommandServiceManager manager = getCommandServiceManager(urlCopy);
manager.addNotifyListener(listener);
// 這里訂閱節點變化事件:即服務節點(zkClient.subscribeChildChanges(serverTypePath, zkChildListener))
// /motan/motan-demo-rpc/com.weibo.motan.demo.service.MotanDemoService/server
subscribeService(urlCopy, manager);
// 這里訂閱數據變化事件:即命令節點(zkClient.subscribeDataChanges(commandPath, zkDataListener);)
// /motan/motan-demo-rpc/command
subscribeCommand(urlCopy, manager);
// 這里會去主動獲取服務節點下的所有服務列表
// /motan/motan-demo-rpc/com.weibo.motan.demo.service.MotanDemoService/server
List<URL> urls = doDiscover(urlCopy);
if (urls != null && urls.size() > 0) {
this.notify(urlCopy, listener, urls);
}
}
- 上述服務URL準備好后,發通知(事件),繼續處理ClusterSupport
// ClusterSupport的notify方法
// refer處理,這里的protocol被ProtocolFilterDecorator包裝了一層,實際是DefaultRpcProtocol
referer = protocol.refer(interfaceClass, refererURL, u);
// DefaultRpcProtocol 中創建createReferer
return new DefaultRpcReferer<T>(clz, url, serviceUrl);
// 下面就是傳輸層的處理了
// 在DefaultRpcReferer中獲取NettyEndpointFactory,并創建NettyClient客戶端
// 然后執行referer(DefaultRpcReferer)初始化
// 調用client.open(); 完成NettyClient的各種配置初始化等
- 再看一下configHandler.refer(interfaceClass, clusters, proxy)處理
@Override
public <T> T refer(Class<T> interfaceClass, List<Cluster<T>> clusters, String proxyType) {
// Motan這里只有JdkProxyFactory
ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getExtension(proxyType);
// 通過JdkProxyFactory獲取代理
return proxyFactory.getProxy(interfaceClass, new RefererInvocationHandler<T>(interfaceClass, clusters));
}
// 獲取代理處理
private void init() {
// 這里獲取一個開關服務,用于在invoke代理時實現降級功能,實現類LocalSwitcherService
String switchName =
this.clusters.get(0).getUrl().getParameter(URLParamType.switcherService.getName(), URLParamType.switcherService.getValue());
switcherService = ExtensionLoader.getExtensionLoader(SwitcherService.class).getExtension(switchName);
}
- 最后將創建的代理賦給ref變量,所以ref實際持有的是Invoke代理類的對象
簡單示意圖
- Cluster收到注冊中心的全量服務列表后,繼續Protocol處理流程
- Filter 這里對Protocol包裝了一層,可以加自己的處理
- switcher,這是代理層增加的,可用于降級處理
client.png