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 java.lang.reflect.Constructor; import org.apache.avro.ipc.Responder; import org.apache.avro.ipc.specific.SpecificResponder; import org.apache.commons.lang.StringUtils; import org.apache.curator.framework.CuratorFramework; import org.apache.thrift.TProcessor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.annotation.JSONField; import com.bfd.harpc.RpcException; import com.bfd.harpc.common.NetUtils; import com.bfd.harpc.common.ServerNode; import com.bfd.harpc.monitor.RpcMonitor; import com.bfd.harpc.proxy.DynamicServiceHandler; import com.bfd.harpc.registry.IRegistry; import com.bfd.harpc.registry.ZkServerRegistry; import com.bfd.harpc.server.IServer; import com.bfd.harpc.server.avro.AvroServer; import com.bfd.harpc.server.thrift.ThriftServer; /** * ???? * <p> * * @author : dsfan * @date : 2015-5-19 */ public class ServerConfig implements IConfigCheck { /** LOGGER */ private final Logger LOGGER = LoggerFactory.getLogger(getClass()); /** ??? */ private String name; /** ? */ private String owner; /** ?19090 */ private int port = 19090; /** ?? */ private String protocol = "thrift"; /** ??,1 */ @JSONField(serialize = false) private int weight = 1; /** ?ip???? */ private String ip; /** ? */ @JSONField(serialize = false) private Object ref; /** ???()??$??? */ private String service; /** ?? */ private boolean monitor; /** ??:s5min */ private int interval = 5 * 60; /** {@link Integer#MAX_VALUE} */ private int maxWorkerThreads = Integer.MAX_VALUE; /** ? ,10 */ private int minWorkerThreads = 10; /** {@link IRegistry} */ private IRegistry registry; /** {@link RpcMonitor} */ private RpcMonitor rpcMonitor; /** {@link IServer} */ private IServer server; /** * ? * <p> * * @throws ClassNotFoundException * ,RpcException */ public void export(RegistryConfig registryConfig) throws ClassNotFoundException, RpcException { // ? check(); // ServerNode serverNode = genServerNode(); IRegistry registry = null; if (registryConfig != null) { CuratorFramework zkClient = registryConfig.obtainZkClient(); if (StringUtils.isEmpty(registryConfig.getAuth())) { throw new RpcException(RpcException.CONFIG_EXCEPTION, "The params 'auth' cannot empty!"); } registry = new ZkServerRegistry(zkClient, service, serverNode.genAddress(), registryConfig.getAuth()); } // RpcMonitor rpcMonitor = null; if (monitor) { rpcMonitor = new RpcMonitor(interval, registryConfig.obtainZkClient(), service, false); } // ? IServer server = createServer(serverNode, rpcMonitor); server.start(); if (server.isStarted()) { this.server = server; this.registry = registry; this.rpcMonitor = rpcMonitor; try { // ? registry.register(genConfigJson()); // ? addShutdownHook(registry, server); } catch (Exception e) { LOGGER.error(e.getMessage(), e); server.stop(); } } else { server.stop(); } } /** * ? * <p> * * @param serverNode * @param rpcMonitor * @return {@link IServer} * @throws ClassNotFoundException */ protected IServer createServer(ServerNode serverNode, RpcMonitor rpcMonitor) throws ClassNotFoundException { IServer server = null; if (StringUtils.equalsIgnoreCase(protocol, "thrift")) { TProcessor processor = reflectProcessor(rpcMonitor, serverNode); server = new ThriftServer(processor, serverNode, maxWorkerThreads, minWorkerThreads, rpcMonitor); } else if (StringUtils.equalsIgnoreCase(protocol, "avro")) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Class<?> protocolIface = reflectProtocolClass(); Responder responder = new SpecificResponder(reflectProtocolClass(), getProxy(classLoader, protocolIface, ref, rpcMonitor, serverNode)); server = new AvroServer(responder, serverNode, maxWorkerThreads, minWorkerThreads, rpcMonitor); } else { throw new RpcException(RpcException.CONFIG_EXCEPTION, "Unsupport protocal,please check the params 'protocal'!"); } return server; } /** * ??TProcessor * <p> * * @param rpcMonitor * @param serverNode * @return TProcessor */ @SuppressWarnings("rawtypes") protected TProcessor reflectProcessor(RpcMonitor rpcMonitor, ServerNode serverNode) { Class serviceClass = getRef().getClass(); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Class<?>[] interfaces = serviceClass.getInterfaces(); if (interfaces.length == 0) { throw new RpcException("Service class should implements Iface!"); } // ??,load "Processor"; TProcessor processor = null; for (Class clazz : interfaces) { String cname = clazz.getSimpleName(); if (!cname.equals("Iface")) { continue; } String pname = clazz.getEnclosingClass().getName() + "$Processor"; try { Class<?> pclass = classLoader.loadClass(pname); Constructor constructor = pclass.getConstructor(clazz); processor = (TProcessor) constructor .newInstance(getProxy(classLoader, clazz, getRef(), rpcMonitor, serverNode)); } catch (Exception e) { throw new RpcException("Refact error,please check your thift gen class!", e.getCause()); } } if (processor == null) { throw new RpcException("Service class should implements $Iface!"); } return processor; } /** * ??? * <p> * * @param classLoader * @param interfaces * @param object * @param rpcMonitor * @param serverNode * @return ?? * @throws ClassNotFoundException */ private Object getProxy(ClassLoader classLoader, Class<?> interfaces, Object object, RpcMonitor rpcMonitor, ServerNode serverNode) throws ClassNotFoundException { DynamicServiceHandler dynamicServiceHandler = new DynamicServiceHandler(); return dynamicServiceHandler.bind(classLoader, interfaces, object, rpcMonitor, serverNode); } /** * ??iface * <p> * * @return {@link Responder} */ @SuppressWarnings("rawtypes") protected Class reflectProtocolClass() { Class serviceClass = getRef().getClass(); Class<?>[] interfaces = serviceClass.getInterfaces(); if (interfaces.length == 0) { throw new RpcException("Service class should implements avro's interface!"); } // ?Responder for (Class clazz : interfaces) { try { clazz.getDeclaredField("PROTOCOL").get(null); return clazz; // return new SpecificResponder(clazz, ref); } catch (Exception e) { } } throw new RpcException("Service class should implements avro's interface!"); } /** * ? {@link ServerNode} * <p> * * @return {@link ServerNode} */ protected ServerNode genServerNode() { String ip = null; if (StringUtils.isNotEmpty(getIp())) { ip = getIp(); } else { ip = NetUtils.getLocalHost(); } if (ip == null) { throw new RpcException("Can't find server ip!"); } return new ServerNode(ip, getPort()); } @Override public void check() throws RpcException { if (StringUtils.isEmpty(service)) { throw new RpcException(RpcException.CONFIG_EXCEPTION, "The params 'service' cannot empty!"); } if (interval < 60) { throw new RpcException(RpcException.CONFIG_EXCEPTION, "The params 'interval' must >= 60!"); } } /** * ??<br/> * ??? * <p> */ public void destory() { if (rpcMonitor != null) { rpcMonitor.destroy(); } if (registry != null) { registry.unregister(); } if (server != null) { server.stop(); } } /** * ??json? * <p> * * @return ?json? */ protected String genConfigJson() { return JSON.toJSONString(this); } /** * ? * <p> * * @param registry * @param server */ protected void addShutdownHook(final IRegistry registry, final IServer server) { Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { if (rpcMonitor != null) { rpcMonitor.destroy(); } if (registry != null) { registry.unregister(); } if (server != null) { server.stop(); } } })); } /** * getter method * * @see ServerConfig#name * @return the name */ public String getName() { return name; } /** * setter method * * @see ServerConfig#name * @param name * the name to set */ public void setName(String name) { this.name = name; } /** * getter method * * @see ServerConfig#owner * @return the owner */ public String getOwner() { return owner; } /** * setter method * * @see ServerConfig#owner * @param owner * the owner to set */ public void setOwner(String owner) { this.owner = owner; } /** * getter method * * @see ServerConfig#port * @return the port */ public int getPort() { return port; } /** * setter method * * @see ServerConfig#port * @param port * the port to set */ public void setPort(int port) { this.port = port; } /** * getter method * * @see ServerConfig#protocol * @return the protocol */ public String getProtocol() { return protocol; } /** * setter method * * @see ServerConfig#protocol * @param protocol * the protocol to set */ public void setProtocol(String protocol) { this.protocol = protocol; } /** * getter method * * @see ServerConfig#weight * @return the weight */ public int getWeight() { return weight; } /** * setter method * * @see ServerConfig#weight * @param weight * the weight to set */ public void setWeight(int weight) { this.weight = weight; } /** * getter method * * @see ServerConfig#ip * @return the ip */ public String getIp() { return ip; } /** * setter method * * @see ServerConfig#ip * @param ip * the ip to set */ public void setIp(String ip) { this.ip = ip; } /** * getter method * * @see ServerConfig#ref * @return the ref */ public Object getRef() { return ref; } /** * setter method * * @see ServerConfig#ref * @param ref * the ref to set */ public void setRef(Object ref) { this.ref = ref; } /** * getter method * * @see ServerConfig#service * @return the service */ public String getService() { return service; } /** * setter method * * @see ServerConfig#service * @param service * the service to set */ public void setService(String service) { this.service = service; } /** * getter method * * @see ServerConfig#monitor * @return the monitor */ public boolean isMonitor() { return monitor; } /** * setter method * * @see ServerConfig#monitor * @param monitor * the monitor to set */ public void setMonitor(boolean monitor) { this.monitor = monitor; } /** * getter method * * @see ServerConfig#interval * @return the interval */ public int getInterval() { return interval; } /** * setter method * * @see ServerConfig#interval * @param interval * the interval to set */ public void setInterval(int interval) { this.interval = interval; } /** * getter method * * @see ServerConfig#maxWorkerThreads * @return the maxWorkerThreads */ public int getMaxWorkerThreads() { return maxWorkerThreads; } /** * setter method * * @see ServerConfig#maxWorkerThreads * @param maxWorkerThreads * the maxWorkerThreads to set */ public void setMaxWorkerThreads(int maxWorkerThreads) { this.maxWorkerThreads = maxWorkerThreads; } /** * getter method * * @see ServerConfig#minWorkerThreads * @return the minWorkerThreads */ public int getMinWorkerThreads() { return minWorkerThreads; } /** * setter method * * @see ServerConfig#minWorkerThreads * @param minWorkerThreads * the minWorkerThreads to set */ public void setMinWorkerThreads(int minWorkerThreads) { this.minWorkerThreads = minWorkerThreads; } }