Java tutorial
/** * Copyright (C) 2015 Baifendian Corporation * * 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.bfd.harpc.config; import org.apache.commons.lang.StringUtils; import org.apache.commons.pool.impl.GenericKeyedObjectPool; import org.apache.thrift.TServiceClient; import org.apache.thrift.TServiceClientFactory; import com.alibaba.fastjson.JSON; import com.bfd.harpc.RpcException; import com.bfd.harpc.client.DefaultInvoker; import com.bfd.harpc.client.Invoker; import com.bfd.harpc.common.NetUtils; import com.bfd.harpc.common.ServerNode; import com.bfd.harpc.heartbeat.HeartBeatManager; import com.bfd.harpc.loadbalance.LoadBalancer; import com.bfd.harpc.loadbalance.LoadBalancerFactory; import com.bfd.harpc.loadbalance.common.DynamicHostSet; import com.bfd.harpc.monitor.RpcMonitor; import com.bfd.harpc.pool.AvroClientPoolFactory; import com.bfd.harpc.pool.TServiceClientPoolFactory; import com.bfd.harpc.proxy.DynamicClientHandler; import com.bfd.harpc.registry.DefaultRegistry; import com.bfd.harpc.registry.IRegistry; import com.bfd.harpc.registry.ZkClientRegistry; /** * ?? * <p> * * @author : dsfan * @date : 2015-5-20 */ public class ClientConfig<T> implements IConfigCheck { /** ??? */ private String name; /** ? */ private String owner; /** ???()??$??? */ private String service; /** ???? */ private String address; /** ?1 */ private int retry = 1; /** ??? */ private String iface; /** ?? */ private String protocol = "thrift"; /** ?? */ private boolean monitor; /** ??:s5min */ private int interval = 5 * 60; /** ?round?roundrandom */ private String loadbalance = "round"; // ??? /** ??ms3s */ private int timeout = 3000; /** */ private int maxActive = 1024; /** ,100 */ private int maxIdle = 100; /** ,0 */ private int minIdle = 0; /** ? */ private int maxWait = 2000; /** ??3min-1 */ private int timeBetweenEvictionRunsMillis = 180000; /** ???false */ private boolean testWhileIdle = false; // ??heartbeat? /** 10s */ private int heartbeat = 10 * 1000; /** ??ms ,3s */ private int heartbeatTimeout = 3000; /** ?3 */ private int heartbeatTimes = 3; /** ?,??ms3s */ private int heartbeatInterval = 3000; /** {@link IRegistry} */ private IRegistry registry; /** {@link RpcMonitor} */ private RpcMonitor rpcMonitor; /** {@link HeartBeatManager} */ private HeartBeatManager<T> heartBeatManager; /** {@link GenericKeyedObjectPool} */ private GenericKeyedObjectPool<ServerNode, T> pool; /** * ? * <p> * * @param registryConfig * @return {client?} * @throws Exception */ public T createProxy(RegistryConfig registryConfig) throws Exception { check(); // ? // IRegistry registry; ServerNode clientNode = new ServerNode(NetUtils.getLocalHost(), 0); if (getAddress() != null) { registry = new DefaultRegistry(getAddress()); } else if (registryConfig != null) { registry = new ZkClientRegistry(service, registryConfig.obtainZkClient(), clientNode); } else { throw new RpcException(RpcException.CONFIG_EXCEPTION, "The params 'addess' and '<registry>' node cannot all unexist!"); } registry.register(genConfigJson()); // RpcMonitor rpcMonitor = null; // client?monitor // if (monitor) { // rpcMonitor = new RpcMonitor(interval, // registryConfig.obtainZkClient(), service, true); // } ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); // Iface? Class<?> objectClass = classLoader.loadClass(iface); GenericKeyedObjectPool<ServerNode, T> pool = bulidClientPool(classLoader, objectClass); DynamicHostSet hostSet = registry.findAllService(); HeartBeatManager<T> heartBeatManager = new HeartBeatManager<T>(hostSet, heartbeat, heartbeatTimeout, heartbeatTimes, heartbeatInterval, pool); heartBeatManager.startHeatbeatTimer(); this.registry = registry; this.rpcMonitor = rpcMonitor; this.heartBeatManager = heartBeatManager; this.pool = pool; // ShutdownHook addShutdownHook(registry, rpcMonitor, heartBeatManager); LoadBalancer<ServerNode> loadBalancer = LoadBalancerFactory.createLoadBalancer(registry.findAllService(), loadbalance, heartBeatManager); Invoker invoker = new DefaultInvoker<T>(clientNode, pool, loadBalancer, retry, rpcMonitor, hostSet); DynamicClientHandler dynamicClientHandler = new DynamicClientHandler(invoker); return dynamicClientHandler.<T>bind(classLoader, objectClass); } /** * client * <p> * * @param classLoader * @param ifaceClass * @throws ClassNotFoundException * @throws InstantiationException * @throws IllegalAccessException */ @SuppressWarnings("unchecked") protected GenericKeyedObjectPool<ServerNode, T> bulidClientPool(ClassLoader classLoader, Class<?> ifaceClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException { // poolConfig GenericKeyedObjectPool.Config poolConfig = new GenericKeyedObjectPool.Config(); poolConfig.maxActive = maxActive; poolConfig.maxIdle = maxIdle; poolConfig.minIdle = minIdle; poolConfig.maxWait = maxWait; poolConfig.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; poolConfig.testWhileIdle = testWhileIdle; if (StringUtils.equalsIgnoreCase(protocol, "thrift")) { // Client.Factory Class<TServiceClientFactory<TServiceClient>> fi = (Class<TServiceClientFactory<TServiceClient>>) classLoader .loadClass(findOutClassName() + "$Client$Factory"); TServiceClientFactory<TServiceClient> clientFactory = fi.newInstance(); TServiceClientPoolFactory<T> clientPool = new TServiceClientPoolFactory<T>(clientFactory, timeout); return new GenericKeyedObjectPool<ServerNode, T>(clientPool, poolConfig); } else if (StringUtils.equalsIgnoreCase(protocol, "avro")) { AvroClientPoolFactory<T> clientPool = new AvroClientPoolFactory<T>(timeout, ifaceClass); return new GenericKeyedObjectPool<ServerNode, T>(clientPool, poolConfig); } else { throw new RpcException(RpcException.CONFIG_EXCEPTION, "Unsupport protocal,please check the params 'protocal'!"); } } /** * ??? * <p> * * @param iface * @return ?? */ private String findOutClassName() { if (iface.contains("$")) { return iface.substring(0, iface.indexOf("$")); } return iface; } @Override public void check() throws RpcException { if (StringUtils.isEmpty(service)) { throw new RpcException(RpcException.CONFIG_EXCEPTION, "The params 'service' cannot empty!"); } if (StringUtils.isEmpty(iface)) { throw new RpcException(RpcException.CONFIG_EXCEPTION, "The params 'iface' cannot empty!"); } if (interval < 60) { throw new RpcException(RpcException.CONFIG_EXCEPTION, "The params 'interval' must >= 60!"); } if (heartbeat < 1000) { throw new RpcException(RpcException.CONFIG_EXCEPTION, "The params 'heartbeat' must >= 1000!"); } } /** * ??<br/> * ?heartbeat? * <p> */ public void destory() { if (rpcMonitor != null) { rpcMonitor.destroy(); } if (registry != null) { registry.unregister(); } if (heartBeatManager != null) { heartBeatManager.stopHeartbeatTimer(); } if (pool != null) { pool.clear(); } } /** * ??json? * <p> * * @return ?json? */ protected String genConfigJson() { return JSON.toJSONString(this); } /** * ? * <p> * * @param registry * @param monitor * @param heartBeatManager */ protected void addShutdownHook(final IRegistry registry, final RpcMonitor monitor, final HeartBeatManager<T> heartBeatManager) { Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { if (monitor != null) { monitor.destroy(); } if (registry != null) { registry.unregister(); } if (heartBeatManager != null) { heartBeatManager.stopHeartbeatTimer(); } if (pool != null) { pool.clear(); } } })); } /** * getter method * * @see ClientConfig#name * @return the name */ public String getName() { return name; } /** * setter method * * @see ClientConfig#name * @param name * the name to set */ public void setName(String name) { this.name = name; } /** * getter method * * @see ClientConfig#owner * @return the owner */ public String getOwner() { return owner; } /** * setter method * * @see ClientConfig#owner * @param owner * the owner to set */ public void setOwner(String owner) { this.owner = owner; } /** * getter method * * @see ClientConfig#service * @return the service */ public String getService() { return service; } /** * setter method * * @see ClientConfig#service * @param service * the service to set */ public void setService(String service) { this.service = service; } /** * getter method * * @see ClientConfig#address * @return the address */ public String getAddress() { return address; } /** * setter method * * @see ClientConfig#address * @param address * the address to set */ public void setAddress(String address) { this.address = address; } /** * getter method * * @see ClientConfig#retry * @return the retry */ public int getRetry() { return retry; } /** * setter method * * @see ClientConfig#retry * @param retry * the retry to set */ public void setRetry(int retry) { this.retry = retry; } /** * getter method * * @see ClientConfig#iface * @return the iface */ public String getIface() { return iface; } /** * setter method * * @see ClientConfig#iface * @param iface * the iface to set */ public void setIface(String iface) { this.iface = iface; } /** * getter method * * @see ClientConfig#protocol * @return the protocol */ public String getProtocol() { return protocol; } /** * setter method * * @see ClientConfig#protocol * @param protocol * the protocol to set */ public void setProtocol(String protocol) { this.protocol = protocol; } /** * getter method * * @see ClientConfig#monitor * @return the monitor */ public boolean isMonitor() { return monitor; } /** * setter method * * @see ClientConfig#monitor * @param monitor * the monitor to set */ public void setMonitor(boolean monitor) { this.monitor = monitor; } /** * getter method * * @see ClientConfig#interval * @return the interval */ public int getInterval() { return interval; } /** * setter method * * @see ClientConfig#interval * @param interval * the interval to set */ public void setInterval(int interval) { this.interval = interval; } /** * getter method * * @see ClientConfig#loadbalance * @return the loadbalance */ public String getLoadbalance() { return loadbalance; } /** * setter method * * @see ClientConfig#loadbalance * @param loadbalance * the loadbalance to set */ public void setLoadbalance(String loadbalance) { this.loadbalance = loadbalance; } /** * getter method * * @see ClientConfig#timeout * @return the timeout */ public int getTimeout() { return timeout; } /** * setter method * * @see ClientConfig#timeout * @param timeout * the timeout to set */ public void setTimeout(int timeout) { this.timeout = timeout; } /** * getter method * * @see ClientConfig#maxActive * @return the maxActive */ public int getMaxActive() { return maxActive; } /** * setter method * * @see ClientConfig#maxActive * @param maxActive * the maxActive to set */ public void setMaxActive(int maxActive) { this.maxActive = maxActive; } /** * getter method * * @see ClientConfig#maxIdle * @return the maxIdle */ public int getMaxIdle() { return maxIdle; } /** * setter method * * @see ClientConfig#maxIdle * @param maxIdle * the maxIdle to set */ public void setMaxIdle(int maxIdle) { this.maxIdle = maxIdle; } /** * getter method * * @see ClientConfig#minIdle * @return the minIdle */ public int getMinIdle() { return minIdle; } /** * setter method * * @see ClientConfig#minIdle * @param minIdle * the minIdle to set */ public void setMinIdle(int minIdle) { this.minIdle = minIdle; } /** * getter method * * @see ClientConfig#maxWait * @return the maxWait */ public int getMaxWait() { return maxWait; } /** * setter method * * @see ClientConfig#maxWait * @param maxWait * the maxWait to set */ public void setMaxWait(int maxWait) { this.maxWait = maxWait; } /** * getter method * * @see ClientConfig#timeBetweenEvictionRunsMillis * @return the timeBetweenEvictionRunsMillis */ public int getTimeBetweenEvictionRunsMillis() { return timeBetweenEvictionRunsMillis; } /** * setter method * * @see ClientConfig#timeBetweenEvictionRunsMillis * @param timeBetweenEvictionRunsMillis * the timeBetweenEvictionRunsMillis to set */ public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) { this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; } /** * getter method * * @see ClientConfig#testWhileIdle * @return the testWhileIdle */ public boolean isTestWhileIdle() { return testWhileIdle; } /** * setter method * * @see ClientConfig#testWhileIdle * @param testWhileIdle * the testWhileIdle to set */ public void setTestWhileIdle(boolean testWhileIdle) { this.testWhileIdle = testWhileIdle; } /** * getter method * * @see ClientConfig#heartbeat * @return the heartbeat */ public int getHeartbeat() { return heartbeat; } /** * setter method * * @see ClientConfig#heartbeat * @param heartbeat * the heartbeat to set */ public void setHeartbeat(int heartbeat) { this.heartbeat = heartbeat; } /** * getter method * * @see ClientConfig#heartbeatTimeout * @return the heartbeatTimeout */ public int getHeartbeatTimeout() { return heartbeatTimeout; } /** * setter method * * @see ClientConfig#heartbeatTimeout * @param heartbeatTimeout * the heartbeatTimeout to set */ public void setHeartbeatTimeout(int heartbeatTimeout) { this.heartbeatTimeout = heartbeatTimeout; } /** * getter method * * @see ClientConfig#heartbeatTimes * @return the heartbeatTimes */ public int getHeartbeatTimes() { return heartbeatTimes; } /** * setter method * * @see ClientConfig#heartbeatTimes * @param heartbeatTimes * the heartbeatTimes to set */ public void setHeartbeatTimes(int heartbeatTimes) { this.heartbeatTimes = heartbeatTimes; } /** * getter method * * @see ClientConfig#heartbeatInterval * @return the heartbeatInterval */ public int getHeartbeatInterval() { return heartbeatInterval; } /** * setter method * * @see ClientConfig#heartbeatInterval * @param heartbeatInterval * the heartbeatInterval to set */ public void setHeartbeatInterval(int heartbeatInterval) { this.heartbeatInterval = heartbeatInterval; } }