/* * Copyright 1999-2011 Alibaba Group. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.dubbo.rpc.protocol.dubbo; import java.net.InetSocketAddress; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.Parameters; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.logger.Logger; import com.alibaba.dubbo.common.logger.LoggerFactory; import com.alibaba.dubbo.common.utils.NetUtils; import com.alibaba.dubbo.remoting.ChannelHandler; import com.alibaba.dubbo.remoting.RemotingException; import com.alibaba.dubbo.remoting.exchange.ExchangeClient; import com.alibaba.dubbo.remoting.exchange.ExchangeHandler; import com.alibaba.dubbo.remoting.exchange.Exchangers; import com.alibaba.dubbo.remoting.exchange.ResponseFuture; /** * dubbo protocol support class. * * @author chao.liuc */ @SuppressWarnings("deprecation") final class LazyConnectExchangeClient implements ExchangeClient{ private final static Logger logger = LoggerFactory.getLogger(LazyConnectExchangeClient.class); private final URL url; private final ExchangeHandler requestHandler; private volatile ExchangeClient client; private final Lock connectLock = new ReentrantLock(); //lazy connect 如果没有初始化时的连接状态 private final boolean initialState ; protected final boolean requestWithWarning; //当调用时warning,出现这个warning,表示程序可能存在bug. static final String REQUEST_WITH_WARNING_KEY = "lazyclient_request_with_warning"; private AtomicLong warningcount = new AtomicLong(0); public LazyConnectExchangeClient(URL url, ExchangeHandler requestHandler) { //lazy connect ,need set send.reconnect = true, to avoid channel bad status. this.url = url.addParameter(Constants.SEND_RECONNECT_KEY, Boolean.TRUE.toString()); this.requestHandler = requestHandler; this.initialState = url.getParameter(Constants.LAZY_CONNECT_INITIAL_STATE_KEY,Constants.DEFAULT_LAZY_CONNECT_INITIAL_STATE); this.requestWithWarning = url.getParameter(REQUEST_WITH_WARNING_KEY, false); } private void initClient() throws RemotingException { if (client != null ) return; if (logger.isInfoEnabled()) { logger.info("Lazy connect to " + url); } connectLock.lock(); try { if (client != null) return; this.client = Exchangers.connect(url, requestHandler); } finally { connectLock.unlock(); } } public ResponseFuture request(Object request) throws RemotingException { warning(request); initClient(); return client.request(request); } public URL getUrl() { return url; } public InetSocketAddress getRemoteAddress() { if (client == null){ return InetSocketAddress.createUnresolved(url.getHost(), url.getPort()); } else { return client.getRemoteAddress(); } } public ResponseFuture request(Object request, int timeout) throws RemotingException { warning(request); initClient(); return client.request(request, timeout); } /** * 如果配置了调用warning,则每调用5000次warning一次. * @param request */ private void warning(Object request){ if (requestWithWarning ){ if (warningcount.get() % 5000 == 0){ logger.warn(new IllegalStateException("safe guard client , should not be called ,must have a bug.")); } warningcount.incrementAndGet() ; } } public ChannelHandler getChannelHandler() { checkClient(); return client.getChannelHandler(); } public boolean isConnected() { if (client == null) { return initialState; } else { return client.isConnected(); } } public InetSocketAddress getLocalAddress() { if (client == null){ return InetSocketAddress.createUnresolved(NetUtils.getLocalHost(), 0); } else { return client.getLocalAddress(); } } public ExchangeHandler getExchangeHandler() { return requestHandler; } public void send(Object message) throws RemotingException { initClient(); client.send(message); } public void send(Object message, boolean sent) throws RemotingException { initClient(); client.send(message, sent); } public boolean isClosed() { if (client != null) return client.isClosed(); else return true; } public void close() { if (client != null) client.close(); } public void close(int timeout) { if (client != null) client.close(timeout); } public void reset(URL url) { checkClient(); client.reset(url); } @Deprecated public void reset(Parameters parameters){ reset(getUrl().addParameters(parameters.getParameters())); } public void reconnect() throws RemotingException { checkClient(); client.reconnect(); } public Object getAttribute(String key) { if (client == null){ return null; } else { return client.getAttribute(key); } } public void setAttribute(String key, Object value) { checkClient(); client.setAttribute(key, value); } public void removeAttribute(String key) { checkClient(); client.removeAttribute(key); } public boolean hasAttribute(String key) { if (client == null){ return false; } else { return client.hasAttribute(key); } } private void checkClient() { if (client == null) { throw new IllegalStateException( "LazyConnectExchangeClient state error. the client has not be init .url:" + url); } } }