首先看初始化方法第一行
/**
* init after constructor.
*/
@PostConstruct
public void init() {
try {
NotifyCenter.registerSubscriber(this);
List<Member> members = serverMemberManager.allMembersWithoutSelf();
refresh(members);
Loggers.CLUSTER
.warn("[ClusterRpcClientProxy] success to refresh cluster rpc client on start up,members ={} ",
members);
} catch (NacosException e) {
Loggers.CLUSTER.warn("[ClusterRpcClientProxy] fail to refresh cluster rpc client,{} ", e.getMessage());
}
}
ClusterRpcClientProxy继承了Subscriber,所以先将自己注册成订阅者,发生MembersChangeEvent事件的时候,会执行onEvent方法
@Override
public void onEvent(MembersChangeEvent event) {
try {
List<Member> members = serverMemberManager.allMembersWithoutSelf();
refresh(members);
} catch (NacosException e) {
Loggers.CLUSTER.warn("[serverlist] fail to refresh cluster rpc client, event:{}, msg: {} ", event, e.getMessage());
}
}
根据以上代码得出结论:ClusterRpcClientProxy初始化和发生MembersChangeEvent事件的时候会执行refresh(members);方法。
继续看refresh方法到底做了什么
/**
* init cluster rpc clients.
*
* @param members cluster server list member list.
*/
private void refresh(List<Member> members) throws NacosException {
//ensure to create client of new members
for (Member member : members) {
if (MemberUtil.isSupportedLongCon(member)) {
createRpcClientAndStart(member, ConnectionType.GRPC);
}
}
//shutdown and remove old members.
Set<Map.Entry<String, RpcClient>> allClientEntrys = RpcClientFactory.getAllClientEntries();
Iterator<Map.Entry<String, RpcClient>> iterator = allClientEntrys.iterator();
List<String> newMemberKeys = members.stream().filter(MemberUtil::isSupportedLongCon)
.map(this::memberClientKey).collect(Collectors.toList());
while (iterator.hasNext()) {
Map.Entry<String, RpcClient> next1 = iterator.next();
if (next1.getKey().startsWith("Cluster-") && !newMemberKeys.contains(next1.getKey())) {
Loggers.CLUSTER.info("member leave,destroy client of member - > : {}", next1.getKey());
RpcClientFactory.getClient(next1.getKey()).shutdown();
iterator.remove();
}
}
}
继续看createRpcClientAndStart
private void createRpcClientAndStart(Member member, ConnectionType type) throws NacosException {
Map<String, String> labels = new HashMap<String, String>(2);
labels.put(RemoteConstants.LABEL_SOURCE, RemoteConstants.LABEL_SOURCE_CLUSTER);
String memberClientKey = memberClientKey(member);
RpcClient client = RpcClientFactory.createClusterClient(memberClientKey, type, labels);
if (!client.getConnectionType().equals(type)) {
Loggers.CLUSTER.info(",connection type changed,destroy client of member - > : {}", member);
RpcClientFactory.destroyClient(memberClientKey);
client = RpcClientFactory.createClusterClient(memberClientKey, type, labels);
}
if (client.isWaitInitiated()) {
Loggers.CLUSTER.info("start a new rpc client to member - > : {}", member);
//one fixed server
client.serverListFactory(new ServerListFactory() {
@Override
public String genNextServer() {
return member.getAddress();
}
@Override
public String getCurrentServer() {
return member.getAddress();
}
@Override
public List<String> getServerList() {
return CollectionUtils.list(member.getAddress());
}
});
client.start();
}
createRpcClientAndStart做了两件事情,创建RpcClient 对象和调用RpcClient 的start方法。我们主要关注start方法。
/**
* Start this client.
*/
public final void start() throws NacosException {
boolean success = rpcClientStatus.compareAndSet(RpcClientStatus.INITIALIZED, RpcClientStatus.STARTING);
if (!success) {
return;
}
clientEventExecutor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("com.alibaba.nacos.client.remote.worker");
t.setDaemon(true);
return t;
}
});
// connection event consumer.
//自旋取出队列连接事件,然后处理
clientEventExecutor.submit(new Runnable() {
@Override
public void run() {
while (!clientEventExecutor.isTerminated() && !clientEventExecutor.isShutdown()) {
ConnectionEvent take = null;
try {
take = eventLinkedBlockingQueue.take();
if (take.isConnected()) {
notifyConnected();
} else if (take.isDisConnected()) {
notifyDisConnected();
}
} catch (Throwable e) {
//Do nothing
}
}
}
});
//从reconnectionSignal这个队列中取出ReconnectContext,然后做处理
clientEventExecutor.submit(new Runnable() {
@Override
public void run() {
while (true) {
try {
if (isShutdown()) {
break;
}
ReconnectContext reconnectContext = reconnectionSignal
.poll(keepAliveTime, TimeUnit.MILLISECONDS);
if (reconnectContext == null) {
//check alive time.
if (System.currentTimeMillis() - lastActiveTimeStamp >= keepAliveTime) {
boolean isHealthy = healthCheck();
if (!isHealthy) {
if (currentConnection == null) {
continue;
}
LoggerUtils.printIfInfoEnabled(LOGGER,
"[{}]Server healthy check fail,currentConnection={}", name,
currentConnection.getConnectionId());
RpcClientStatus rpcClientStatus = RpcClient.this.rpcClientStatus.get();
if (RpcClientStatus.SHUTDOWN.equals(rpcClientStatus)) {
break;
}
boolean success = RpcClient.this.rpcClientStatus
.compareAndSet(rpcClientStatus, RpcClientStatus.UNHEALTHY);
if (success) {
reconnectContext = new ReconnectContext(null, false);
} else {
continue;
}
} else {
lastActiveTimeStamp = System.currentTimeMillis();
continue;
}
} else {
continue;
}
}
if (reconnectContext.serverInfo != null) {
//clear recommend server if server is not in server list.
boolean serverExist = false;
for (String server : getServerListFactory().getServerList()) {
ServerInfo serverInfo = resolveServerInfo(server);
if (serverInfo.getServerIp().equals(reconnectContext.serverInfo.getServerIp())) {
serverExist = true;
reconnectContext.serverInfo.serverPort = serverInfo.serverPort;
break;
}
}
if (!serverExist) {
LoggerUtils.printIfInfoEnabled(LOGGER,
"[{}] Recommend server is not in server list ,ignore recommend server {}", name,
reconnectContext.serverInfo.getAddress());
reconnectContext.serverInfo = null;
}
}
reconnect(reconnectContext.serverInfo, reconnectContext.onRequestFail);
} catch (Throwable throwable) {
//Do nothing
}
}
}
});
//connect to server ,try to connect to server sync once, async starting if fail.
Connection connectToServer = null;
//将rpc客户端状态设置成启动中
rpcClientStatus.set(RpcClientStatus.STARTING);
//默认重试三次
int startUpRetryTimes = RETRY_TIMES;
while (startUpRetryTimes > 0 && connectToServer == null) {
try {
startUpRetryTimes--;
//获取客服务端ip端口信息
ServerInfo serverInfo = nextRpcServer();
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Try to connect to server on start up, server: {}", name,
serverInfo);
//连接服务端
connectToServer = connectToServer(serverInfo);
} catch (Throwable e) {
LoggerUtils.printIfWarnEnabled(LOGGER,
"[{}]Fail to connect to server on start up, error message={}, start up retry times left: {}",
name, e.getMessage(), startUpRetryTimes);
}
}
if (connectToServer != null) {
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Success to connect to server [{}] on start up,connectionId={}",
name, connectToServer.serverInfo.getAddress(), connectToServer.getConnectionId());
this.currentConnection = connectToServer;
//连接成功,将rpc客户端状态设置成运行中
rpcClientStatus.set(RpcClientStatus.RUNNING);
//往eventLinkedBlockingQueue队列中放入一个连接事件
eventLinkedBlockingQueue.offer(new ConnectionEvent(ConnectionEvent.CONNECTED));
} else {
//连接失败,往reconnectionSignal队列中放入ReconnectContext对象
switchServerAsync();
}
//注册handle,将处理request
registerServerRequestHandler(new ConnectResetRequestHandler());
//register client detection request.
registerServerRequestHandler(new ServerRequestHandler() {
@Override
public Response requestReply(Request request) {
if (request instanceof ClientDetectionRequest) {
return new ClientDetectionResponse();
}
return null;
}
});
}
这个start方法看起来非常的长。我们先不要着急,一个一个看。
// connection event consumer.
//自旋取出队列连接事件,然后处理
clientEventExecutor.submit(new Runnable() {
@Override
public void run() {
while (!clientEventExecutor.isTerminated() && !clientEventExecutor.isShutdown()) {
ConnectionEvent take = null;
try {
take = eventLinkedBlockingQueue.take();
if (take.isConnected()) {
notifyConnected();
} else if (take.isDisConnected()) {
notifyDisConnected();
}
} catch (Throwable e) {
//Do nothing
}
}
}
});
start方法做的第一件事是往一个线程池中提交了一个任务,这个任务从eventLinkedBlockingQueue这个队列中取出一个ConnectionEvent 对象,然后做了处理。
//从reconnectionSignal这个队列中取出ReconnectContext,然后做处理
clientEventExecutor.submit(new Runnable() {
@Override
public void run() {
while (true) {
try {
if (isShutdown()) {
break;
}
ReconnectContext reconnectContext = reconnectionSignal
.poll(keepAliveTime, TimeUnit.MILLISECONDS);
if (reconnectContext == null) {
//check alive time.
if (System.currentTimeMillis() - lastActiveTimeStamp >= keepAliveTime) {
boolean isHealthy = healthCheck();
if (!isHealthy) {
if (currentConnection == null) {
continue;
}
LoggerUtils.printIfInfoEnabled(LOGGER,
"[{}]Server healthy check fail,currentConnection={}", name,
currentConnection.getConnectionId());
RpcClientStatus rpcClientStatus = RpcClient.this.rpcClientStatus.get();
if (RpcClientStatus.SHUTDOWN.equals(rpcClientStatus)) {
break;
}
boolean success = RpcClient.this.rpcClientStatus
.compareAndSet(rpcClientStatus, RpcClientStatus.UNHEALTHY);
if (success) {
reconnectContext = new ReconnectContext(null, false);
} else {
continue;
}
} else {
lastActiveTimeStamp = System.currentTimeMillis();
continue;
}
} else {
continue;
}
}
if (reconnectContext.serverInfo != null) {
//clear recommend server if server is not in server list.
boolean serverExist = false;
for (String server : getServerListFactory().getServerList()) {
ServerInfo serverInfo = resolveServerInfo(server);
if (serverInfo.getServerIp().equals(reconnectContext.serverInfo.getServerIp())) {
serverExist = true;
reconnectContext.serverInfo.serverPort = serverInfo.serverPort;
break;
}
}
if (!serverExist) {
LoggerUtils.printIfInfoEnabled(LOGGER,
"[{}] Recommend server is not in server list ,ignore recommend server {}", name,
reconnectContext.serverInfo.getAddress());
reconnectContext.serverInfo = null;
}
}
reconnect(reconnectContext.serverInfo, reconnectContext.onRequestFail);
} catch (Throwable throwable) {
//Do nothing
}
}
}
});
也是往线程池中提交了一个任务。这个任务我们暂时只知道是从reconnectionSignal这个队列中取出ReconnectContext,然后做处理。
继续看
//connect to server ,try to connect to server sync once, async starting if fail.
Connection connectToServer = null;
//将rpc客户端状态设置成启动中
rpcClientStatus.set(RpcClientStatus.STARTING);
//默认重试三次
int startUpRetryTimes = RETRY_TIMES;
while (startUpRetryTimes > 0 && connectToServer == null) {
try {
startUpRetryTimes--;
//获取客服务端ip端口信息
ServerInfo serverInfo = nextRpcServer();
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Try to connect to server on start up, server: {}", name,
serverInfo);
//连接服务端
connectToServer = connectToServer(serverInfo);
} catch (Throwable e) {
LoggerUtils.printIfWarnEnabled(LOGGER,
"[{}]Fail to connect to server on start up, error message={}, start up retry times left: {}",
name, e.getMessage(), startUpRetryTimes);
}
}
if (connectToServer != null) {
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Success to connect to server [{}] on start up,connectionId={}",
name, connectToServer.serverInfo.getAddress(), connectToServer.getConnectionId());
this.currentConnection = connectToServer;
//连接成功,将rpc客户端状态设置成运行中
rpcClientStatus.set(RpcClientStatus.RUNNING);
//往eventLinkedBlockingQueue队列中放入一个连接事件
eventLinkedBlockingQueue.offer(new ConnectionEvent(ConnectionEvent.CONNECTED));
} else {
//连接失败,往reconnectionSignal队列中放入ReconnectContext对象
switchServerAsync();
}
//注册handle,将处理request
registerServerRequestHandler(new ConnectResetRequestHandler());
//register client detection request.
registerServerRequestHandler(new ServerRequestHandler() {
@Override
public Response requestReply(Request request) {
if (request instanceof ClientDetectionRequest) {
return new ClientDetectionResponse();
}
return null;
}
});
这段代码就是以默认重试三次的方式去连接其中一个member,如果连接完成则往eventLinkedBlockingQueue队列中放入一个连接事件, //连接失败,往reconnectionSignal队列中放入ReconnectContext对象。第一次提交的任务会自旋处理连接事件,而第二次提交的任务会自旋处理ReconnectContext也就是连接失败的事件。