获取invoker对象
a)注册消费端的临时节点
b) 订阅以下的节点
/dubbo/com.test.ITestService/providers
/dubbo/com.test.ITestService/configurators
/dubbo/com.test.ITestService/routers
c) 当这些节点下的子节点发生变化: 刷新本地的RequestDirector的本地urlInvokerMap列表
第一次初始化invoker,创建DubboInvoker。启动netty客户端连接
将invoker包装在代理对象Proxy$0中。返回代理对象
主流程
消费端接口初始化或者有提供者节点变化时,通知更新本地zookeeper缓存文件
消费端接口初始化或者有提供者节点变化时,通知更新本地的invoker列表 urlInvokerMap
在更新本地的invoker列表时,没有生成过Invoker,需要指定Invoker且netty客户端连接服务端
ReferenceBean 实现了FactoryBean, 那么在从io容器获取Bean时,就调用了Object getObject()
private transient volatile T ref; //保存代理对象
当有对象时,直接返回,否则初始化
public synchronized T get() {
if (destroyed) {
throw new IllegalStateException("Already destroyed!");
}
if (ref == null) {
init();
}
return ref;
}
init()组装参数,最终调用 ref = createProxy(map);
//用户指定URL,指定的URL可能是对点对直连地址,也可能是注册中心URL
if (url != null && url.length() > 0) {
String[] us = Constants.SEMICOLON_SPLIT_PATTERN.split(url);
if (us != null && us.length > 0) {
for (String u : us) {
URL url = URL.valueOf(u);
if (url.getPath() == null || url.getPath().length() == 0) {
url = url.setPath(interfaceName);
}
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
urls.add(url.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
} else {
urls.add(ClusterUtils.mergeUrl(url, map));
}
}
}
} else {
//通过注册中心配置拼装URL
List us = loadRegistries(false);
if (us != null && !us.isEmpty()) {
for (URL u : us) {
URL monitorUrl = loadMonitor(u);
if (monitorUrl != null) {
map.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
}
urls.add(u.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
}
}
if (urls == null || urls.isEmpty()) {
throw new IllegalStateException();
}
}
if (urls.size() == 1) {
invoker = refprotocol.refer(interfaceClass, urls.get(0));
} else {
List> invokers = new ArrayList>();
URL registryURL = null;
for (URL url : urls) {
invokers.add(refprotocol.refer(interfaceClass, url));
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
registryURL = url;
}
}
//有注册中心的地址, StaticDirectory
if (registryURL != null) {
URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
invoker = cluster.join(new StaticDirectory(u, invokers));
} else { // not a registry url
invoker = cluster.join(new StaticDirectory(invokers));
}
}
refprotocol.refer(interfaceClass, url)
refprotocol这里的对象是RegistryProtocol
1.获取Registry:ZookeeperRegistry
//将registry协议改成zookeeper。
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);
}
2.向zookeeper注册consumer://10.118.14.24/com.test.ITestService节点
registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY,
Constants.CHECK_KEY, String.valueOf(false)));
a)将url保存到注册列表中
b)创建提供者的临时节点
c)出现异常时,开启启动时检测,直接抛出异常;否则记录到failedRegistered,等待定时重新注册
3.创建RegistryDirectory,并且订阅consumer://10.118.14.24/com.test.ITestService
consumer://10.118.14.24/com.test.ITestService?category=providers,configurators,routers&side=consumer…
RegistryDirectory directory = new RegistryDirectory(type, url);
directory.setRegistry(registry);
directory.setProtocol(protocol);
URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, NetUtils.getLocalHost(), 0,
type.getName(), directory.getUrl().getParameters());
//加参数category:providers,configurators,routers
directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
Constants.PROVIDERS_CATEGORY
+ "," + Constants.CONFIGURATORS_CATEGORY
+ "," + Constants.ROUTERS_CATEGORY));
4.cluster.join(directory);
默认是FailoverCluster, 所以返回的invoker对象是MockClusterInvoker(FailoverClusterInvoker)
mock=com.alibaba.dubbo.rpc.cluster.support.wrapper.MockClusterWrapper
failover=com.alibaba.dubbo.rpc.cluster.support.FailoverCluster
failfast=com.alibaba.dubbo.rpc.cluster.support.FailfastCluster
failsafe=com.alibaba.dubbo.rpc.cluster.support.FailsafeCluster
failback=com.alibaba.dubbo.rpc.cluster.support.FailbackCluster
forking=com.alibaba.dubbo.rpc.cluster.support.ForkingCluster
available=com.alibaba.dubbo.rpc.cluster.support.AvailableCluster
mergeable=com.alibaba.dubbo.rpc.cluster.support.MergeableCluster
broadcast=com.alibaba.dubbo.rpc.cluster.support.BroadcastCluster
上面创建了invoker对象
proxyFactory.getProxy(invoker)
StubProxyFactoryWrapper(JavassistProxyFactory)
stub=com.alibaba.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper
jdk=com.alibaba.dubbo.rpc.proxy.jdk.JdkProxyFactory
javassist=com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory
获取代理方法
public T getProxy(Invoker invoker, Class>[] interfaces) {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
拦截器
public class InvokerInvocationHandler implements InvocationHandler {
private final Invoker> invoker;
public InvokerInvocationHandler(Invoker> handler){
this.invoker = handler;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
Class>[] parameterTypes = method.getParameterTypes();
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
if ("toString".equals(methodName) && parameterTypes.length == 0) {
return invoker.toString();
}
if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
return invoker.hashCode();
}
if ("equals".equals(methodName) && parameterTypes.length == 1) {
return invoker.equals(args[0]);
}
return invoker.invoke(new RpcInvocation(method, args)).recreate();
}
}
从ioc获取的对象是代理对象Proxy$0
交给InvokerInvocationHandler进行处理->MockClusterInvoker -> FailoverClusterInvoker-> RegistryDirectory->invoke列表
以下是分支流程=======================
RegistryDirectory 实现了NotifyListener, 本身就是个监听器
调用RegistryDirectory的subscribe,registry就是ZookeeperRegistry
而订阅直接交给registry去处理, 而其中的this是RegistryDirectory
public void subscribe(URL url) {
setConsumerUrl(url);
registry.subscribe(url, this);
}
一:url和RegistryDirectory保存在subscribed中
consumer://10.118.14.24/com.test.ITestService?category=providers,configurators,routers&side=consumer…
二:ZookeeperRegistry 订阅url
调用ZookeeperRegistry.doSubscribe(final URL url, final NotifyListener listener) ;
consumer://10.118.14.24/10.118.14.24/com.test.ITestService?category=providers,configurators,routers&default.check=false&default.cluster=failfast&default.timeout=60000&dubbo=2.8.4&interface=com.insaic.itbase.service.BusinessNoGeneratorService&logger=slf4j&methods=test,save&pid=10132&revision=1.0-20191223.094125-383&side=consumer×tamp=1577323081022&version=1.0.0
/dubbo/com.test.ITestService/providers
/dubbo/com.test.ITestService/configurators
/dubbo/com.test.ITestService/routers
private String[] toCategoriesPath(URL url) {
String[] categroies;
//接口是* ,那么categroies 就是全量
if (Constants.ANY_VALUE.equals(url.getParameter(Constants.CATEGORY_KEY))) {
categroies = new String[] {Constants.PROVIDERS_CATEGORY, Constants.CONSUMERS_CATEGORY,
Constants.ROUTERS_CATEGORY, Constants.CONFIGURATORS_CATEGORY};
} else {
//从url中获取category
categroies = url.getParameter(Constants.CATEGORY_KEY, new String[] {Constants.DEFAULT_CATEGORY});
}
String[] paths = new String[categroies.length];
for (int i = 0; i < categroies.length; i ++) {
//dubbo+接口+category
paths[i] = toServicePath(url) + Constants.PATH_SEPARATOR + categroies[i];
}
return paths;
}
以下是遍历这些路径path
-------> 1. 获取ChildListener子节点监听器
查看是否创建了监听器
没有,对/dubbo/com.test.ITestService/providers
/dubbo/com.test.ITestService/configurators
/dubbo/com.test.ITestService/routers
初始化监听器
子节点变化通知当前节点子节点有变化,见下一节
ConcurrentMap listeners = zkListeners.get(url);
if (listeners == null) {
zkListeners.putIfAbsent(url, new ConcurrentHashMap());
listeners = zkListeners.get(url);
}
ChildListener zkListener = listeners.get(listener);
if (zkListener == null) {
listeners.putIfAbsent(listener, new ChildListener() {
public void childChanged(String parentPath, List currentChilds) {
ZookeeperRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChilds));
}
});
zkListener = listeners.get(listener);
}
------->2. 创建持久化节点,并且增加子节点监听器
/dubbo/com.test.ITestService/providers
/dubbo/com.test.ITestService/configurators
/dubbo/com.test.ITestService/routers
zkClient.create(path, false);
List children = zkClient.addChildListener(path, zkListener);
------->3. 获取当前com.test.ITestService的下的providers、routes、configurators所有的子节点
在第一步遍历providers时,当前子节点是
dubbo://10.118.22.51:20710/com.test.ITestService?default.cluster=failfast&default.timeout=3000&dubbo=2.8.4&generic=false&interface=com.test.ITestService&logger=slf4j&methods=test,save&pid=3091&revision=1.0.0&side=provider×tamp=1576650287438&version=1.0.0
当configurators和routers当前没有子节点,就封装成
configurators:
empty://10.118.14.24/com.test.ITestService?&category=configurators&side=consumer×tamp=1577329888735&version=1.0.0
routers:
empty://10.118.14.24/com.test.ITestService?&category=routers&side=consumer×tamp=1577329888735&version=1.0.0
List children = zkClient.addChildListener(path, zkListener);
if (children != null) {
urls.addAll(toUrlsWithEmpty(url, path, children));
}
//当没有子节点时,对consumer地址将协议改成empty,增加对应的category
private List toUrlsWithEmpty(URL consumer, String path, List providers) {
List urls = toUrlsWithoutEmpty(consumer, providers);
if (urls.isEmpty()) {
int i = path.lastIndexOf('/');
String category = i < 0 ? path : path.substring(i + 1);
URL empty = consumer.setProtocol(Constants.EMPTY_PROTOCOL).addParameter(Constants.CATEGORY_KEY, category);
urls.add(empty);
}
return urls;
}
notify(url, listener, urls);
url:消费者的url
urls: com.test.ITestService的下的providers、routes、configurators变化的子节点。
listener: RegistryDirectory
new ChildListener() {
public void childChanged(String parentPath, List currentChilds) {
ZookeeperRegistry.this.notify(url, listener,
toUrlsWithEmpty(url, parentPath, currentChilds));
}
});
providers、routes、configurators任意一个的子节点发生变化就调用notify。
url: 当前的消费者url
currentChilds是所有的子节点路径
parentPath:providers、routes、configurators
1. 对当前的url进行分类。按照category(providers、routes、configurators)分类, 并且放入到notified中
Map> result = new HashMap>();
for (URL u : urls) {
if (UrlUtils.isMatch(url, u)) {
String category = u.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
List categoryList = result.get(category);
if (categoryList == null) {
categoryList = new ArrayList();
result.put(category, categoryList);
}
categoryList.add(u);
}
}
2. 保存urls到文件中和properties
private void saveProperties(URL url) {
if (file == null) {
return;
}
//组装内容
StringBuilder buf = new StringBuilder();
Map> categoryNotified = notified.get(url);
if (categoryNotified != null) {
for (List us : categoryNotified.values()) {
for (URL u : us) {
if (buf.length() > 0) {
//空格分隔符
buf.append(' ');
}
buf.append(u.toFullString());
}
}
}
//放入到properties
properties.setProperty(url.getServiceKey(), buf.toString());
long version = lastCacheChanged.incrementAndGet();
//保存文件
if (syncSaveFile) {
doSaveProperties(version);
} else {
registryCacheExecutor.execute(new SaveProperties(version));
}
}
先创建dubbo-registry-10.118.22.55.cache.lock 空文件, 对空文件进行上锁,保存文件。然后再释放锁。
public void doSaveProperties(long version) {
// 当前版本小于最后一次,不再保存
if(version < lastCacheChanged.get()){
return;
}
if (file == null) {
return;
}
Properties newProperties = new Properties();
// 保存之前先读取一遍,防止多个注册中心之间冲突
InputStream in = null;
if (file.exists()) {
in = new FileInputStream(file);
newProperties.load(in);
}
// 保存
try {
newProperties.putAll(properties);
//先创建dubbo-registry-10.118.22.55.cache.lock 空文件
File lockfile = new File(file.getAbsolutePath() + ".lock");
if (!lockfile.exists()) {
lockfile.createNewFile();
}
//先对空文件进行上锁
RandomAccessFile raf = new RandomAccessFile(lockfile, "rw");
try {
FileChannel channel = raf.getChannel();
try {
FileLock lock = channel.tryLock();
if (lock == null) {
throw new IOException("");
}
// 保存
try {
if (! file.exists()) {
file.createNewFile();
}
FileOutputStream outputFile = new FileOutputStream(file);
try {
newProperties.store(outputFile, "Dubbo Registry Cache");
} finally {
outputFile.close();
}
} finally {
lock.release();
}
} finally {
channel.close();
}
} finally {
raf.close();
}
} catch (Throwable e) {
if (version < lastCacheChanged.get()) {
return;
} else {
registryCacheExecutor.execute(new SaveProperties(lastCacheChanged.incrementAndGet()));
}
logger.warn("Failed to save registry store file, cause: " + e.getMessage(), e);
}
}
3.listener.notify(categoryList); 刷新本地的invoker
见下一节
List invokerUrls = new ArrayList();
List routerUrls = new ArrayList();
List configuratorUrls = new ArrayList();
for (URL url : urls) {
String protocol = url.getProtocol();
String category = url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
if ("routers".equals(category) || "route".equals(protocol)) {
routerUrls.add(url);
} else if ("configurators".equals(category) || "override".equals(protocol)) {
configuratorUrls.add(url);
} else if (“”providers“”.equals(category)) {
invokerUrls.add(url);
}
}
根据协议来判断来做处理
override=com.alibaba.dubbo.rpc.cluster.configurator.override.OverrideConfiguratorFactory
absent=com.alibaba.dubbo.rpc.cluster.configurator.absent.AbsentConfiguratorFactory
file=com.alibaba.dubbo.rpc.cluster.router.file.FileRouterFactory
script=com.alibaba.dubbo.rpc.cluster.router.script.ScriptRouterFactory
condition=com.alibaba.dubbo.rpc.cluster.router.condition.ConditionRouterFactory
private void refreshInvoker(List invokerUrls){
//....
this.forbidden = false; // 允许访问
//旧的invoker列表
Map> oldUrlInvokerMap = this.urlInvokerMap;
if (invokerUrls.size() ==0 ){
return;
}
// 将URL列表转成Invoker列表
Map> newUrlInvokerMap = toInvokers(invokerUrls) ;
// 换方法名映射Invoker列表
Map>> newMethodInvokerMap = toMethodInvokers(newUrlInvokerMap);
//没有新的invoker,则不再处理
if (newUrlInvokerMap == null || newUrlInvokerMap.size() == 0 ){
return ;
}
this.methodInvokerMap = multiGroup ? toMergeMethodInvokerMap(newMethodInvokerMap) : newMethodInvokerMap;
//保存到本地urlInvokerMap中
this.urlInvokerMap = newUrlInvokerMap;
try{
//销毁未使用的invoker列表(在旧的invoker列表中,不在新的invoker列表)
destroyUnusedInvokers(oldUrlInvokerMap,newUrlInvokerMap);
}catch (Exception e) {
logger.warn("destroyUnusedInvokers error. ", e);
}
}
重点:获取新的invoker列表
a) 合并url参数 顺序为override >Consumer > Provider
b) 查看urlInvokerMap中是否有了,没有重新生成消费端的invoker代理对象
new InvokerDelegete(protocol.refer(serviceType, url), url, providerUrl);见下一节
c)销毁 未使用的invoker列表( in(老的invoker列表) and not in(新的invoker列表))
private Map> toInvokers(List urls) {
Map> newUrlInvokerMap = new HashMap>();
if(urls == null || urls.size() == 0){
return newUrlInvokerMap;
}
Set keys = new HashSet();
String queryProtocols = this.queryMap.get(Constants.PROTOCOL_KEY);
for (URL providerUrl : urls) {
if (Constants.EMPTY_PROTOCOL.equals(providerUrl.getProtocol())) {
continue;
}
//查看协议是否支持
if (! ExtensionLoader.getExtensionLoader(Protocol.class).hasExtension(providerUrl.getProtocol())) {
continue;
}
//合并url (提供者的url和消费者的url进行合并)
URL url = mergeUrl(providerUrl);
String key = url.toFullString(); // URL参数是排序的
if (keys.contains(key)) { // 重复URL
continue;
}
keys.add(key);
// 缓存key为没有合并消费端参数的URL,不管消费端如何合并参数,如果服务端URL发生变化,则重新refer
Map> localUrlInvokerMap = this.urlInvokerMap; // local reference
Invoker invoker = localUrlInvokerMap == null ? null : localUrlInvokerMap.get(key);
if (invoker == null) { // 缓存中没有,重新refer
//...查看是否增加disabled或者enabled
boolean enabled = true;
if (enabled) {
invoker = new InvokerDelegete(protocol.refer(serviceType, url), url, providerUrl);
}
if (invoker != null) { // 将新的引用放入缓存
newUrlInvokerMap.put(key, invoker);
}
}else {
newUrlInvokerMap.put(key, invoker);
}
}
keys.clear();
return newUrlInvokerMap;
}
合并url参数 顺序为override > -D >Consumer > Provider
private URL mergeUrl(URL providerUrl){
providerUrl = ClusterUtils.mergeUrl(providerUrl, queryMap); // 合并消费端参数
//对提供者进行处理
List localConfigurators = this.configurators;
if (localConfigurators != null && localConfigurators.size() > 0) {
for (Configurator configurator : localConfigurators) {
providerUrl = configurator.configure(providerUrl);
}
}
providerUrl = providerUrl.addParameter(Constants.CHECK_KEY, String.valueOf(false)); // 不检查连接是否成功,总是创建Invoker!
//directoryUrl 与 override 合并是在notify的最后,这里不能够处理
this.overrideDirectoryUrl = this.overrideDirectoryUrl.addParametersIfAbsent(providerUrl.getParameters()); // 合并提供者参数
return providerUrl;
}
ProtocolFilterWrapper:
过滤所有的consumer下的Filter,循环对invoker进行包装
public Invoker refer(Class serviceType, URL url) throws RpcException {
optimizeSerialization(url);
DubboInvoker invoker = new DubboInvoker(serviceType, url, getClients(url), invokers);
invokers.add(invoker);
return invoker;
}
private ExchangeClient[] getClients(URL url){
//是否共享连接
boolean service_share_connect = false;
int connections = url.getParameter(Constants.CONNECTIONS_KEY, 0);
//如果connections不配置,则共享连接,否则每服务每连接
if (connections == 0){
service_share_connect = true;
connections = 1;
}
ExchangeClient[] clients = new ExchangeClient[connections];
for (int i = 0; i < clients.length; i++) {
if (service_share_connect){
clients[i] = getSharedClient(url);
} else {
clients[i] = initClient(url);
}
}
return clients;
}
/**
*获取共享连接
*/
private ExchangeClient getSharedClient(URL url){
String key = url.getAddress();
ReferenceCountExchangeClient client = referenceClientMap.get(key);
if ( client != null ){
if ( !client.isClosed()){
client.incrementAndGetCount();
return client;
} else {
referenceClientMap.remove(key);
}
}
ExchangeClient exchagneclient = initClient(url);
client = new ReferenceCountExchangeClient(exchagneclient, ghostClientMap);
referenceClientMap.put(key, client);
ghostClientMap.remove(key);
return client;
}
初始化客户端
/**
* 创建新连接.
*/
private ExchangeClient initClient(URL url) {。
//默认开启heartbeat
url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT));
ExchangeClient client ;
try {
//设置连接应该是lazy的
if (url.getParameter(Constants.LAZY_CONNECT_KEY, false)){
client = new LazyConnectExchangeClient(url ,requestHandler);
} else {
client = Exchangers.connect(url ,requestHandler);
}
} catch (RemotingException e) {
throw new RpcException("Fail to create remoting client for service(" + url
+ "): " + e.getMessage(), e);
}
return client;
}
创建客户端连接 Exchangers.connect(url ,requestHandler)
new HeaderExchangeClient(Transporters.connect(url, new DecodeHandler(new HeaderExchangeHandler(handler))))
heatbeatTimer = scheduled.scheduleWithFixedDelay(
new HeartBeatTask( new HeartBeatTask.ChannelProvider() {
public Collection getChannels() {
return Collections.singletonList( HeaderExchangeClient.this );
}
}, heartbeat, heartbeatTimeout),
heartbeat, heartbeat, TimeUnit.MILLISECONDS );
//上次读取的时间
Long lastRead = ( Long ) channel.getAttribute(
HeaderExchangeHandler.KEY_READ_TIMESTAMP );
//上次写入的时间
Long lastWrite = ( Long ) channel.getAttribute(
HeaderExchangeHandler.KEY_WRITE_TIMESTAMP );
//在时间内, 发送心跳信息给服务端
if ( ( lastRead != null && now - lastRead > heartbeat )
|| ( lastWrite != null && now - lastWrite > heartbeat ) ) {
Request req = new Request();
req.setVersion( "2.0.0" );
req.setTwoWay( true );
req.setEvent( Request.HEARTBEAT_EVENT );
channel.send( req );
}
//超时了,重连
if ( lastRead != null && now - lastRead > heartbeatTimeout ) {
if (channel instanceof Client) {
((Client)channel).reconnect();
} else {
channel.close();
}
}
初始化
protected void doOpen() throws Throwable {
NettyHelper.setNettyLoggerFactory();
bootstrap = new ClientBootstrap(channelFactory);
// config
// @see org.jboss.netty.channel.socket.SocketChannelConfig
bootstrap.setOption("keepAlive", true);
bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("connectTimeoutMillis", getTimeout());
final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this);
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", adapter.getDecoder());
pipeline.addLast("encoder", adapter.getEncoder());
pipeline.addLast("handler", nettyHandler);
return pipeline;
}
});
}
连接
启动定时,查看是否连接,没有的话,重新连接
protected void connect() throws RemotingException {
connectLock.lock();
try {
if (isConnected()) {
return;
}
//启动
initConnectStatusCheckCommand();
doConnect();
if (! isConnected()) {
throw new RemotingException();
}
reconnect_count.set(0);
reconnect_error_log_flag.set(false);
} finally {
connectLock.unlock();
}
}
等待服务器的响应
protected void doConnect() throws Throwable {
long start = System.currentTimeMillis();
ChannelFuture future = bootstrap.connect(getConnectAddress());
try{
//等待
boolean ret = future.awaitUninterruptibly(getConnectTimeout(), TimeUnit.MILLISECONDS);
//连接成功
if (ret && future.isSuccess()) {
Channel newChannel = future.getChannel();
newChannel.setInterestOps(Channel.OP_READ_WRITE);
try {
// 关闭旧的连接
Channel oldChannel = NettyClient.this.channel; // copy reference
if (oldChannel != null) {
try {
oldChannel.close();
} finally {
NettyChannel.removeChannelIfDisconnected(oldChannel);
}
}
} finally {
//新连接也是关闭的,将新连接关闭
if (NettyClient.this.isClosed()) {
try {
newChannel.close();
} finally {
NettyClient.this.channel = null;
NettyChannel.removeChannelIfDisconnected(newChannel);
}
} else {
//赋值
NettyClient.this.channel = newChannel;
}
}
} else if (future.getCause() != null) {
throw new RemotingException();
} else {
throw new RemotingException();
}
}finally{
if (! isConnected()) {
future.cancel();
}
}
}