在还没有认真分析源码之前,我根据以前阅读微服务框架的思路,去分析这样几个问题
- 客户端如何获取服务节点列表
- 客户端如何维持与服务之间的链接,这种链接是长连接还是短连接,使用的方式/框架是什么?
- 客户端如何实现服务端调用的负载均衡,还是说负载均衡由硬件来处理(网络层来处理)。
- 客户端与服务端数据是怎样通信的?序列化协议?
- 客户端与服务端连接出现问题如何处理?
这是我暂时想到的,当然微服务框架之间的处理,远不止这些,这些算是入门读懂一些框架,接下来我就来具体分析。
// 从本地启动的配置
CommunicatorConfig cfg = new CommunicatorConfig();
// 从本地启动的Communcator
Communicator communicator = CommunicatorFactory.getInstance().getCommunicator(cfg);
//warn 若是部署在tars平台启动的, 只能使用下面的构造器获取communcator
//Communicator communicator = CommunicatorFactory.getInstance().getCommunicator();
HelloPrx proxy = communicator.stringToProxy(HelloPrx.class, "TestApp.HelloServer.HelloObj@tcp -h 127.0.0.1 -p 18601 -t 60000");
//同步调用
String ret = proxy.hello(1000, "Hello World");
System.out.println(ret);
- CommunicatorConfig:客户端协调器的配置文件(超时配置呀,等等一些列配置信息)
- Communicator:正在的协调调用者。
- stringToProxy:将我们的Servant封装成代理类,ObjectProxy也就是我们后面获取的Servant客户端都是ObjectProxy,直接看invoke方法即可。
几个关键的类
1. CommunicatorConfig
2. Communicator
3. ServantProxyFactory
public <T> Object getServantProxy(Class<T> clazz, String objName, String setDivision, ServantProxyConfig servantProxyConfig,
LoadBalance loadBalance, ProtocolInvoker<T> protocolInvoker) {
String key = setDivision != null ? clazz.getSimpleName() + objName + setDivision : clazz.getSimpleName() + objName;
Object proxy = cache.get(key);
if (proxy == null) {
lock.lock();
try {
proxy = cache.computeIfAbsent(key, param -> {
ObjectProxy<T> objectProxy = communicator.getObjectProxyFactory().getObjectProxy(clazz, objName, setDivision, servantProxyConfig, loadBalance, protocolInvoker);
return createProxy(clazz, objectProxy);
});
} finally {
lock.unlock();
}
}
return proxy;
}
管理ObjectProxyFactory,如果缓存有就从缓存中取,没有就生产
4.ObjectProxyFactory
public <T> ObjectProxy<T> getObjectProxy(Class<T> api, String objName, String setDivision, ServantProxyConfig servantProxyConfig,
LoadBalance<T> loadBalance, ProtocolInvoker<T> protocolInvoker) throws ClientException {
if (servantProxyConfig == null) {
servantProxyConfig = createServantProxyConfig(objName, setDivision);
} else {
servantProxyConfig.setCommunicatorId(communicator.getId());
servantProxyConfig.setModuleName(communicator.getCommunicatorConfig().getModuleName(), communicator.getCommunicatorConfig().isEnableSet(), communicator.getCommunicatorConfig().getSetDivision());
servantProxyConfig.setLocator(communicator.getCommunicatorConfig().getLocator());
if (StringUtils.isNotEmpty(setDivision)) {
servantProxyConfig.setSetDivision(setDivision);
}
}
updateServantEndpoints(servantProxyConfig);
if (loadBalance == null) {
loadBalance = createLoadBalance(servantProxyConfig);
}
if (protocolInvoker == null) {
protocolInvoker = createProtocolInvoker(api, servantProxyConfig);
}
return new ObjectProxy<T>(api, servantProxyConfig, loadBalance, protocolInvoker, communicator);
}
生产ObjectProxy
- 创建ServantProxyConfig:就是Servant服务的配置信息,每个服务配置可能不同
- updateServantEndpoints
private void updateServantEndpoints(ServantProxyConfig cfg) {
CommunicatorConfig communicatorConfig = communicator.getCommunicatorConfig();
String endpoints = null;
if (!ParseTools.hasServerNode(cfg.getObjectName()) && !cfg.isDirectConnection() && !communicatorConfig.getLocator().startsWith(cfg.getSimpleObjectName())) {
try {
/** query server nodes from registerServer */
if (RegisterManager.getInstance().getHandler() != null) {
endpoints = ParseTools.parse(RegisterManager.getInstance().getHandler().query(cfg.getSimpleObjectName()),
cfg.getSimpleObjectName());
} else {
endpoints = communicat