public RequrlQuality getQuality() { if (getTotalValue() > configManager.getIntValue(KEY_REQUEST_QUALITY_THRESHOLD_TOTAL, 20)) { float failedRate = getFailedPercent(); if (failedRate < configManager.getFloatValue(KEY_REQUEST_QUALITY_FAILED_PERCENT_GOOD, 1f)) { quality = RequrlQuality.REQURL_QUALITY_GOOD; } else if (failedRate >= configManager.getFloatValue(KEY_REQUEST_QUALITY_FAILED_PERCENT_GOOD, 1f) && failedRate < configManager.getFloatValue(KEY_REQUEST_QUALITY_FAILED_PERCENT_NORMAL, 5f)) { quality = RequrlQuality.REQURL_QUALITY_NORNAL; } else if (failedRate >= configManager.getFloatValue(KEY_REQUEST_QUALITY_FAILED_PERCENT_NORMAL, 5f)) { quality = RequrlQuality.REQURL_QUALITY_BAD; } } return quality; }
public void addClientRequest(InvokerContext context, boolean failed) { if (configManager.getBooleanValue(KEY_REQUEST_QUALITY_AUTO, false) && context.getClient() != null) { String address = context.getClient().getAddress(); ConcurrentHashMap<String, ConcurrentHashMap<Integer, Quality>> requestSecondQuality = addrReqUrlSecondQualities.get(address); if (requestSecondQuality == null) { requestSecondQuality = new ConcurrentHashMap<String, ConcurrentHashMap<Integer, Quality>>(); ConcurrentHashMap<String, ConcurrentHashMap<Integer, Quality>> last = addrReqUrlSecondQualities.putIfAbsent(address, requestSecondQuality); if (last != null) { requestSecondQuality = last; } } String requestUrl = getRequestUrl(context); ConcurrentHashMap<Integer, Quality> secondQuality = requestSecondQuality.get(requestUrl); if (secondQuality == null) { secondQuality = new ConcurrentHashMap<Integer, Quality>(); ConcurrentHashMap<Integer, Quality> last = requestSecondQuality.putIfAbsent(requestUrl, secondQuality); if (last != null) { secondQuality = last; } } int currentSecond = Calendar.getInstance().get(Calendar.SECOND); Quality quality = secondQuality.get(currentSecond); if (quality == null) { quality = new Quality(0, 0); Quality last = secondQuality.putIfAbsent(currentSecond, quality); if (last != null) { quality = last; } } quality.total.incrementAndGet(); if (failed) { quality.failed.incrementAndGet(); } } }
static { configManager.getBooleanValue(KEY_REQUEST_QUALITY_AUTO, false); configManager.getIntValue(KEY_REQUEST_QUALITY_THRESHOLD_TOTAL, 20); configManager.getFloatValue(KEY_REQUEST_QUALITY_FAILED_PERCENT_GOOD, 1f); configManager.getFloatValue(KEY_REQUEST_QUALITY_FAILED_PERCENT_NORMAL, 5f); }
public boolean isEnableRequestQualityRoute() { return configManager.getBooleanValue(KEY_REQUEST_QUALITY_AUTO, false); }
public int getWriteBufferLowWater() { return configManager.getIntValue( Constants.KEY_WRITE_BUFFER_LOW_WATER, Constants.DEFAULT_WRITE_BUFFER_LOW_WATER); }
public class NettyClient extends AbstractClient { private static final Logger logger = LoggerLoader.getLogger(NettyClient.class); private ClientBootstrap bootstrap; private Channel channel; private String host; private int port = ServerConfig.DEFAULT_PORT; private String address; private volatile boolean connected = false; private volatile boolean closed = false; private volatile boolean active = true; private ConnectInfo connectInfo; public static final int CLIENT_CONNECTIONS = Runtime.getRuntime().availableProcessors(); private static ConfigManager configManager = ConfigManagerLoader.getConfigManager(); private static ExecutorService bossExecutor = Executors.newCachedThreadPool(new DefaultThreadFactory("Pigeon-Netty-Client-Boss")); private static ExecutorService workExecutor = Executors.newCachedThreadPool(new DefaultThreadFactory("Pigeon-Netty-Client-Worker")); private static final int bossCount = configManager.getIntValue("pigeon.invoker.netty.bosscount", 1); private static final int workerCount = configManager.getIntValue( "pigeon.invoker.netty.workercount", Runtime.getRuntime().availableProcessors() * 2); private static ChannelFactory channelFactory = new NioClientSocketChannelFactory(bossExecutor, workExecutor, bossCount, workerCount); private static final int connectTimeout = configManager.getIntValue(Constants.KEY_CONNECT_TIMEOUT, Constants.DEFAULT_CONNECT_TIMEOUT); public int getWriteBufferHighWater() { return configManager.getIntValue( Constants.KEY_WRITE_BUFFER_HIGH_WATER, Constants.DEFAULT_WRITE_BUFFER_HIGH_WATER); } public int getWriteBufferLowWater() { return configManager.getIntValue( Constants.KEY_WRITE_BUFFER_LOW_WATER, Constants.DEFAULT_WRITE_BUFFER_LOW_WATER); } public NettyClient(ConnectInfo connectInfo) { this.host = connectInfo.getHost(); this.port = connectInfo.getPort(); this.connectInfo = connectInfo; this.address = host + ":" + port; this.bootstrap = new ClientBootstrap(channelFactory); this.bootstrap.setPipelineFactory(new NettyClientPipelineFactory(this)); this.bootstrap.setOption("tcpNoDelay", true); this.bootstrap.setOption("keepAlive", true); this.bootstrap.setOption("reuseAddress", true); this.bootstrap.setOption("connectTimeoutMillis", connectTimeout); this.bootstrap.setOption("writeBufferHighWaterMark", getWriteBufferHighWater()); this.bootstrap.setOption("writeBufferLowWaterMark", getWriteBufferLowWater()); } public synchronized void connect() { if (this.connected) { return; } logger.info("client is connecting to " + this.host + ":" + this.port); ChannelFuture future = null; try { future = bootstrap.connect(new InetSocketAddress(host, port)); if (future.awaitUninterruptibly(connectTimeout, TimeUnit.MILLISECONDS)) { if (future.isSuccess()) { Channel newChannel = future.getChannel(); try { // 关闭旧的连接 Channel oldChannel = this.channel; if (oldChannel != null) { logger.info("close old netty channel " + oldChannel); try { oldChannel.close(); } catch (Throwable t) { } } } finally { this.channel = newChannel; } logger.info("client is connected to " + this.host + ":" + this.port); this.connected = true; } else { logger.info("client is not connected to " + this.host + ":" + this.port); } } else { logger.info("timeout while connecting to " + this.host + ":" + this.port); } } catch (Throwable e) { logger.info("error while connecting to " + this.host + ":" + this.port, e); } } @Override public InvocationResponse doWrite(InvocationRequest request, Callback callback) throws NetworkException { Object[] msg = new Object[] {request, callback}; ChannelFuture future = null; if (channel == null) { logger.error("channel is null ^^^^^^^^^^^^^^"); } else { try { future = channel.write(msg); } catch (Exception e) { throw new NetworkException("remote call failed:" + request, e); } if (request.getMessageType() == Constants.MESSAGE_TYPE_SERVICE || request.getMessageType() == Constants.MESSAGE_TYPE_HEART) { future.addListener(new MsgWriteListener(request)); } } return null; } public void connectionException(Object attachment, Throwable e) { this.connected = false; connectionException(this, attachment, e); } private void connectionException(Client client, Object attachment, Throwable e) { logger.info("exception while connecting to " + client, e); if (attachment == null) { return; } Object[] msg = (Object[]) attachment; if (msg[0] instanceof InvokerContext) { InvokerContext invokerContext = (InvokerContext) msg[0]; InvocationRequest request = invokerContext.getRequest(); if (request.getMessageType() == Constants.MESSAGE_TYPE_SERVICE && msg[1] != null) { try { Callback callback = (Callback) msg[1]; if (client != null) { client.write(request, callback); } else { logger.error("no client found with service:" + request.getServiceName()); } } catch (Throwable ex) { logger.error("", ex); } logger.error("", e); } } } /** @return the connected */ public boolean isConnected() { return connected; } public boolean isActive() { return active && HeartBeatListener.isActiveAddress(address); } public void setActive(boolean active) { this.active = active; } @Override public boolean isWritable() { return this.channel.isWritable(); } /** @return the host */ public String getHost() { return host; } public int getPort() { return this.port; } /** @return the address */ public String getAddress() { return address; } public boolean equals(Object obj) { if (obj instanceof NettyClient) { NettyClient nc = (NettyClient) obj; return this.address.equals(nc.getAddress()); } else { return super.equals(obj); } } @Override public int hashCode() { return address.hashCode(); } @Override public void close() { logger.info("close client:" + this.host + ":" + this.port); closed = true; channel.close(); } @Override public String toString() { return this.getAddress() + ", connected:" + this.isConnected() + ", active:" + this.isActive(); } public class MsgWriteListener implements ChannelFutureListener { private InvocationRequest request; public MsgWriteListener(InvocationRequest request) { this.request = request; } public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { return; } if (request.getMessageType() != Constants.MESSAGE_TYPE_HEART) { connected = false; } InvocationResponse response = ProviderUtils.createFailResponse(request, future.getCause()); processResponse(response); } } @Override public ConnectInfo getConnectInfo() { return connectInfo; } @Override public boolean isDisposable() { return false; } @Override public void dispose() {} @Override public String getProtocol() { return Constants.PROTOCOL_DEFAULT; } }