package com.hqyg.disjob.rpc.client.proxy; import io.netty.bootstrap.Bootstrap; import java.net.InetSocketAddress; import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.lang3.StringUtils; import org.apache.commons.pool2.BasePooledObjectFactory; import com.hqyg.disjob.common.Constants; import com.hqyg.disjob.common.exception.EjobAbstractUncheckException; import com.hqyg.disjob.common.exception.RpcServiceException; import com.hqyg.disjob.common.exception.TransportException; import com.hqyg.disjob.common.util.LoggerUtil; import com.hqyg.disjob.rpc.client.HURL; import com.hqyg.disjob.rpc.client.HURLParamType; import com.hqyg.disjob.rpc.codec.Response; import com.hqyg.disjob.rpc.codec.RpcRequest; import com.hqyg.disjob.rpc.codec.RpcResponse; /** * 1、netty client初始化 * 2、连接池初始化 * 3、编解码初始化 * 4、heartbeat初始化 * 5、断连重连 * @author Disjob * */ public class RpcClient extends AbstractRpcPoolClient{ private AtomicLong errorCount = new AtomicLong(0); private int maxClientConnection = 10;//最大连接数 private InetSocketAddress remoteAddress = null; private InetSocketAddress localAddress = null; public RpcClient(HURL hurl) { super(hurl); } @Override public Response request(RpcRequest request) throws TransportException { boolean async = hurl.getMethodParameter(request.getData().getMethodName(), "", HURLParamType.async.getName(), HURLParamType.async.getBooleanValue()); return request(request, async); } private Response request(RpcRequest request, boolean async) throws TransportException { Channel channel = null; Response response = null; try { channel = borrowObject(request.getData().getRequestId());//这里borrow 到的一根channel 经过validate 之后是一定可用的。 if(channel == null){ response = new RpcResponse(); response.setException("class name:"+request.getData().getClassName()+"method name :"+request.getData().getMethodName()+" borrow a channel is null."); }else{ response = writeMessage(channel.getChannel(), request); } } catch (Exception e) { e.printStackTrace(); handlerException(request, response, e); invalidateObject(channel); }finally{ if(channel !=null){ returnObject(channel); } } return asyncResponse(response, async); } private void handlerException(RpcRequest request, Response response, Exception e) { LoggerUtil.error("NettyClient request Error: url=" + hurl.getUri() + " " + request.toString() + "requestid:"+request.getData().getRequestId()+e.getMessage(),e); if(response !=null && (!StringUtils.isNotEmpty(response.getException() ))){ response.setException("channel.request occur error,"+e.getMessage()); } if (e instanceof EjobAbstractUncheckException) { throw (EjobAbstractUncheckException) e; } else { e.printStackTrace(); throw new RpcServiceException("NettyClient request RpcServiceException: url=" + hurl.getUri() + " "+ request.toString(), e); } } /** * 如果async是false,那么同步获取response的数据 * @param response * @param async * @return */ private Response asyncResponse(Response response, boolean async) { return new RpcResponse(response); } @Override public boolean open() { synchronized (RpcClient.class) { String serverKey = RpcClientCache.getRpcClientKey(hurl); RpcClient client = RpcClientCache.rpcClientPool.get(serverKey); if (client != null && client.isAvailable()) { return false; } initBootstrap(); if(Constants.isCanConnPool){ initPool(false); }else{ connect(Constants.RECON_COUNT_FAIL); } LoggerUtil.info("NettyClient Open finished: url={}", hurl); } return true; } /** * 增加调用失败的次数: * 如果连续失败的次数 >= maxClientConnection, 那么把client设置成不可用状态 */ void incrErrorCount() { long count = errorCount.incrementAndGet(); if(count < maxClientConnection){ return ; } synchronized (this) { count = errorCount.longValue(); if (count >= maxClientConnection) { LoggerUtil.error("NettyClient unavailable Error: url=" + hurl.getIdentity() + " "+ hurl.getServerPortStr()); } } } void resetErrorCount() { errorCount.set(0); } public Bootstrap getBootstrap() { return bootstrap; } public HURL getHurl() { return hurl; } @Override protected BasePooledObjectFactory<Channel> createChannelFactory() { return new ChannelPoolFactory(this); } public InetSocketAddress getLocalAddress() { return localAddress; } public InetSocketAddress getRemoteAddress() { return remoteAddress; } public boolean isClosed() { return false; } public boolean isAvailable() { if(Constants.isCanConnPool){ return true ; } io.netty.channel.Channel channel= ServerLinkedService.getChannel(getChannelKey(), this); if(channel == null){ return false ; } return channel.isActive(); } public RpcResponse writerAndFlush(RpcRequest request){ if(request == null){ return null ; } return writeMessage(ServerLinkedService.getChannel(getChannelKey(),this), request); } }