├── README.md ├── pom.xml └── src ├── main └── java │ └── rpc │ └── xp │ ├── client │ ├── Client.java │ ├── ProxyInterface.java │ ├── ResponseHandler.java │ ├── ResultInfo.java │ └── zk │ │ └── Observer.java │ ├── common │ ├── CommonContext.java │ ├── RequestDecoder.java │ ├── RequestEncoder.java │ ├── ResponseDecoder.java │ ├── ResponseEncoder.java │ ├── RpcRequest.java │ ├── RpcResponse.java │ ├── SerializationUtil.java │ ├── ServiceInfo.java │ └── zk │ │ ├── InfoCallBack.java │ │ └── ZkUtil.java │ └── server │ ├── Invoker.java │ ├── RequestHandler.java │ ├── Server.java │ └── zk │ └── Publisher.java └── test └── java ├── com └── xp │ └── service │ ├── ITest.java │ └── TestImpl.java └── rpc └── test ├── RpcClient.java ├── RpcServer.java └── ZkTest.java /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xpbob/lightrpc/d6b5f1ad0610b4628910813cfe23e2eb08c4599c/README.md -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | nettyTest 5 | nettyTest 6 | 0.0.1-SNAPSHOT 7 | 8 | 9 | io.netty 10 | netty-all 11 | 4.1.24.Final 12 | 13 | 14 | com.dyuproject.protostuff 15 | protostuff-core 16 | 1.0.8 17 | 18 | 19 | com.dyuproject.protostuff 20 | protostuff-runtime 21 | 1.0.8 22 | 23 | 24 | 25 | org.apache.zookeeper 26 | zookeeper 27 | 3.4.9 28 | 29 | 30 | com.alibaba 31 | fastjson 32 | 1.2.47 33 | 34 | 35 | 36 | 37 | org.objenesis 38 | objenesis 39 | 2.1 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/client/Client.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.client; 2 | 3 | import io.netty.bootstrap.Bootstrap; 4 | import io.netty.channel.Channel; 5 | import io.netty.channel.ChannelFuture; 6 | import io.netty.channel.ChannelInitializer; 7 | import io.netty.channel.ChannelPipeline; 8 | import io.netty.channel.EventLoopGroup; 9 | import io.netty.channel.nio.NioEventLoopGroup; 10 | import io.netty.channel.socket.nio.NioSocketChannel; 11 | import rpc.xp.common.RequestEncoder; 12 | import rpc.xp.common.ResponseDecoder; 13 | 14 | public class Client { 15 | private Channel channel; 16 | private String id; 17 | 18 | public void connect(String ip, int port) throws InterruptedException { 19 | EventLoopGroup worker = new NioEventLoopGroup(); 20 | Bootstrap b = new Bootstrap(); 21 | b.group(worker).channel(NioSocketChannel.class).handler(new ChannelInitializer() { 22 | 23 | @Override 24 | protected void initChannel(Channel ch) throws Exception { 25 | ChannelPipeline pipeline = ch.pipeline(); 26 | pipeline.addLast(new RequestEncoder()); 27 | pipeline.addLast(new ResponseDecoder()); 28 | pipeline.addLast(new ResponseHandler()); 29 | } 30 | 31 | }); 32 | 33 | ChannelFuture sync = b.connect(ip, port).sync(); 34 | channel = sync.channel(); 35 | id = ip + ":" + port; 36 | 37 | } 38 | 39 | 40 | 41 | @Override 42 | public int hashCode() { 43 | final int prime = 31; 44 | int result = 1; 45 | result = prime * result + ((id == null) ? 0 : id.hashCode()); 46 | return result; 47 | } 48 | 49 | 50 | 51 | @Override 52 | public boolean equals(Object obj) { 53 | if (this == obj) 54 | return true; 55 | if (obj == null) 56 | return false; 57 | if (getClass() != obj.getClass()) 58 | return false; 59 | Client other = (Client) obj; 60 | if (id == null) { 61 | if (other.id != null) 62 | return false; 63 | } else if (!id.equals(other.id)) 64 | return false; 65 | return true; 66 | } 67 | 68 | 69 | 70 | public void write(Object obj) { 71 | channel.writeAndFlush(obj); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/client/ProxyInterface.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.client; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | import java.lang.reflect.Proxy; 6 | import java.util.UUID; 7 | import java.util.concurrent.SynchronousQueue; 8 | 9 | import rpc.xp.client.zk.Observer; 10 | import rpc.xp.common.RpcRequest; 11 | 12 | public class ProxyInterface { 13 | public static T getProxy(final Class clazz) { 14 | return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, new InvocationHandler() { 15 | 16 | @Override 17 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 18 | RpcRequest request = new RpcRequest(); 19 | request.setMethodName(method.getName()); 20 | request.setClassName(clazz.getName()); 21 | Class[] parameterTypes = method.getParameterTypes(); 22 | request.setArgs(args); 23 | String id = UUID.randomUUID().toString(); 24 | request.setId(id); 25 | SynchronousQueue queue = new SynchronousQueue(); 26 | ResultInfo.putSunchronousQuee(id, queue); 27 | Observer.send(request, clazz.getName()); 28 | return queue.take(); 29 | } 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/client/ResponseHandler.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.client; 2 | 3 | import java.util.concurrent.SynchronousQueue; 4 | 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.channel.SimpleChannelInboundHandler; 7 | import rpc.xp.common.RpcResponse; 8 | 9 | public class ResponseHandler extends SimpleChannelInboundHandler { 10 | 11 | @Override 12 | protected void channelRead0(ChannelHandlerContext ctx, RpcResponse msg) throws Exception { 13 | String id = msg.getId(); 14 | SynchronousQueue synchronousQueue = ResultInfo.getSynchronousQueue(id); 15 | synchronousQueue.put(msg.getResult()); 16 | ResultInfo.removeById(id); 17 | } 18 | 19 | @Override 20 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 21 | ctx.channel().close(); 22 | } 23 | 24 | @Override 25 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 26 | ctx.channel().close(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/client/ResultInfo.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.client; 2 | 3 | import java.util.concurrent.ConcurrentHashMap; 4 | import java.util.concurrent.SynchronousQueue; 5 | 6 | public class ResultInfo { 7 | 8 | private static ConcurrentHashMap mapInfo = new ConcurrentHashMap<>(); 9 | 10 | public static void putSunchronousQuee(String id, SynchronousQueue queue) { 11 | mapInfo.put(id, queue); 12 | } 13 | 14 | public static SynchronousQueue getSynchronousQueue(String id) { 15 | return mapInfo.get(id); 16 | } 17 | public static void removeById(String id){ 18 | mapInfo.remove(id); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/client/zk/Observer.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.client.zk; 2 | 3 | import java.util.HashMap; 4 | import java.util.HashSet; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.Random; 8 | import java.util.Set; 9 | 10 | import com.alibaba.fastjson.JSONObject; 11 | 12 | import rpc.xp.client.Client; 13 | import rpc.xp.common.CommonContext; 14 | import rpc.xp.common.RpcRequest; 15 | import rpc.xp.common.ServiceInfo; 16 | import rpc.xp.common.zk.InfoCallBack; 17 | import rpc.xp.common.zk.ZkUtil; 18 | 19 | public class Observer implements InfoCallBack { 20 | 21 | public static volatile Map> services = new HashMap<>(); 22 | 23 | private ZkUtil zkUtil; 24 | 25 | public Observer(String address) { 26 | zkUtil = new ZkUtil(address); 27 | zkUtil.CreateIfNotExist(CommonContext.PATH); 28 | try { 29 | List inofAndWatcher = zkUtil.getInofAndWatcher(CommonContext.PATH, this); 30 | getLastList(inofAndWatcher); 31 | } catch (Exception e) { 32 | e.printStackTrace(); 33 | } 34 | 35 | } 36 | 37 | public static void send(RpcRequest request, String className) { 38 | Set set = services.get(className); 39 | if (set != null && !set.isEmpty()) { 40 | Client[] array = set.toArray(new Client[0]); 41 | //random 42 | Client client = array[new Random().nextInt(array.length)]; 43 | client.write(request); 44 | } 45 | } 46 | 47 | @Override 48 | public void getLastList(List lists) { 49 | Map> serviceTmp = new HashMap<>(); 50 | if (lists != null && !lists.isEmpty()) { 51 | for (String node : lists) { 52 | String info; 53 | try { 54 | info = new String(zkUtil.getData(CommonContext.PATH + "/" + node)); 55 | ServiceInfo parse = JSONObject.parseObject(info, ServiceInfo.class); 56 | String address = parse.toString(); 57 | List interfaces = parse.getInterfaces(); 58 | if (interfaces != null && !interfaces.isEmpty()) { 59 | for (String service : interfaces) { 60 | Set set = serviceTmp.get(service); 61 | if (set == null) { 62 | set = new HashSet(); 63 | } 64 | if (!set.contains(address)) { 65 | Client client = new Client(); 66 | client.connect(parse.getIp(), parse.getPort()); 67 | set.add(client); 68 | } 69 | serviceTmp.put(service, set); 70 | 71 | } 72 | } 73 | } catch (Exception e) { 74 | e.printStackTrace(); 75 | } 76 | 77 | } 78 | 79 | } 80 | 81 | services = serviceTmp; 82 | 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/common/CommonContext.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.common; 2 | 3 | public interface CommonContext { 4 | public static final String PATH = "/xp"; 5 | public static final int ZK_TIMEOUT = 5000; 6 | 7 | 8 | 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/common/RequestDecoder.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.common; 2 | 3 | import java.util.List; 4 | 5 | import io.netty.buffer.ByteBuf; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.handler.codec.ByteToMessageDecoder; 8 | 9 | public class RequestDecoder extends ByteToMessageDecoder { 10 | 11 | @Override 12 | protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { 13 | 14 | if (in.readableBytes() < 4) { 15 | return; 16 | } 17 | int index = in.readerIndex(); 18 | int readInt = in.readInt(); 19 | if (in.readableBytes() < readInt) { 20 | in.readerIndex(index); 21 | return; 22 | } 23 | byte[] bytes = new byte[readInt]; 24 | in.readBytes(bytes); 25 | RpcRequest request = SerializationUtil.deserializeFromByte(bytes, RpcRequest.class); 26 | out.add(request); 27 | 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/common/RequestEncoder.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.common; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.MessageToByteEncoder; 6 | 7 | public class RequestEncoder extends MessageToByteEncoder { 8 | 9 | @Override 10 | protected void encode(ChannelHandlerContext ctx, RpcRequest msg, ByteBuf out) throws Exception { 11 | byte[] serializeToByte = SerializationUtil.serializeToByte(msg); 12 | out.writeInt(serializeToByte.length); 13 | out.writeBytes(serializeToByte); 14 | 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/common/ResponseDecoder.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.common; 2 | 3 | import java.util.List; 4 | 5 | import io.netty.buffer.ByteBuf; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.handler.codec.ByteToMessageDecoder; 8 | 9 | public class ResponseDecoder extends ByteToMessageDecoder { 10 | 11 | @Override 12 | protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { 13 | // TODO Auto-generated method stub 14 | if (in.readableBytes() < 4) { 15 | return; 16 | } 17 | int index = in.readerIndex(); 18 | int readInt = in.readInt(); 19 | if (in.readableBytes() < readInt) { 20 | in.readerIndex(index); 21 | return; 22 | } 23 | byte[] bytes = new byte[readInt]; 24 | in.readBytes(bytes); 25 | RpcResponse response = SerializationUtil.deserializeFromByte(bytes, RpcResponse.class); 26 | out.add(response); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/common/ResponseEncoder.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.common; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.MessageToByteEncoder; 6 | 7 | public class ResponseEncoder extends MessageToByteEncoder { 8 | 9 | @Override 10 | protected void encode(ChannelHandlerContext ctx, RpcResponse msg, ByteBuf out) throws Exception { 11 | byte[] serializeToByte = SerializationUtil.serializeToByte(msg); 12 | out.writeInt(serializeToByte.length); 13 | out.writeBytes(serializeToByte); 14 | 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/common/RpcRequest.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.common; 2 | 3 | public class RpcRequest { 4 | 5 | private String id; 6 | private String className; 7 | private String methodName; 8 | private Object[] args; 9 | private Class[] parameterTypes; 10 | 11 | 12 | 13 | 14 | public Class[] getParameterTypes() { 15 | return parameterTypes; 16 | } 17 | 18 | public void setParameterTypes(Class[] parameterTypes) { 19 | this.parameterTypes = parameterTypes; 20 | } 21 | 22 | public String getId() { 23 | return id; 24 | } 25 | 26 | public void setId(String id) { 27 | this.id = id; 28 | } 29 | 30 | public String getClassName() { 31 | return className; 32 | } 33 | 34 | public void setClassName(String className) { 35 | this.className = className; 36 | } 37 | 38 | public String getMethodName() { 39 | return methodName; 40 | } 41 | 42 | public void setMethodName(String methodName) { 43 | this.methodName = methodName; 44 | } 45 | 46 | public Object[] getArgs() { 47 | return args; 48 | } 49 | 50 | public void setArgs(Object[] args) { 51 | this.args = args; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/common/RpcResponse.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.common; 2 | 3 | public class RpcResponse { 4 | 5 | private String id; 6 | private Object result; 7 | 8 | public String getId() { 9 | return id; 10 | } 11 | 12 | public void setId(String id) { 13 | this.id = id; 14 | } 15 | 16 | public Object getResult() { 17 | return result; 18 | } 19 | 20 | public void setResult(Object result) { 21 | this.result = result; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/common/SerializationUtil.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.common; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | import org.objenesis.Objenesis; 7 | import org.objenesis.ObjenesisStd; 8 | 9 | import com.dyuproject.protostuff.LinkedBuffer; 10 | import com.dyuproject.protostuff.ProtobufIOUtil; 11 | import com.dyuproject.protostuff.Schema; 12 | import com.dyuproject.protostuff.runtime.RuntimeSchema; 13 | 14 | public class SerializationUtil { 15 | private static Map, Schema> cachedSchema = new ConcurrentHashMap<>(); 16 | 17 | private static Objenesis objenesis = new ObjenesisStd(true); 18 | 19 | private SerializationUtil() { 20 | } 21 | 22 | @SuppressWarnings("unchecked") 23 | private static Schema getSchema(Class cls) { 24 | Schema schema = (Schema) cachedSchema.get(cls); 25 | if (schema == null) { 26 | schema = RuntimeSchema.createFrom(cls); 27 | if (schema != null) { 28 | cachedSchema.put(cls, schema); 29 | } 30 | } 31 | return schema; 32 | } 33 | 34 | @SuppressWarnings("unchecked") 35 | public static String serializeToString(T obj) { 36 | Class cls = (Class) obj.getClass(); 37 | LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); 38 | try { 39 | Schema schema = getSchema(cls); 40 | return new String(ProtobufIOUtil.toByteArray(obj, schema, buffer), "ISO8859-1"); 41 | } catch (Exception e) { 42 | throw new IllegalStateException(e.getMessage(), e); 43 | } finally { 44 | buffer.clear(); 45 | } 46 | } 47 | 48 | public static T deserializeFromString(String data, Class cls) { 49 | try { 50 | T message = (T) objenesis.newInstance(cls); 51 | Schema schema = getSchema(cls); 52 | ProtobufIOUtil.mergeFrom(data.getBytes("ISO8859-1"), message, schema); 53 | return message; 54 | } catch (Exception e) { 55 | throw new IllegalStateException(e.getMessage(), e); 56 | } 57 | } 58 | 59 | 60 | @SuppressWarnings("unchecked") 61 | public static byte[] serializeToByte(T obj) { 62 | Class cls = (Class) obj.getClass(); 63 | LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); 64 | try { 65 | Schema schema = getSchema(cls); 66 | return ProtobufIOUtil.toByteArray(obj, schema, buffer); 67 | } catch (Exception e) { 68 | throw new IllegalStateException(e.getMessage(), e); 69 | } finally { 70 | buffer.clear(); 71 | } 72 | } 73 | 74 | public static T deserializeFromByte(byte[] data, Class cls) { 75 | try { 76 | T message = (T) objenesis.newInstance(cls); 77 | Schema schema = getSchema(cls); 78 | ProtobufIOUtil.mergeFrom(data, message, schema); 79 | return message; 80 | } catch (Exception e) { 81 | throw new IllegalStateException(e.getMessage(), e); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/common/ServiceInfo.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.common; 2 | 3 | import java.util.List; 4 | 5 | public class ServiceInfo { 6 | private String ip; 7 | private int port; 8 | private List interfaces; 9 | 10 | public ServiceInfo(){} 11 | 12 | 13 | 14 | public ServiceInfo(String ip, int port, List interfaces) { 15 | super(); 16 | this.ip = ip; 17 | this.port = port; 18 | this.interfaces = interfaces; 19 | } 20 | 21 | public String getIp() { 22 | return ip; 23 | } 24 | 25 | public void setIp(String ip) { 26 | this.ip = ip; 27 | } 28 | 29 | public int getPort() { 30 | return port; 31 | } 32 | 33 | public void setPort(int port) { 34 | this.port = port; 35 | } 36 | 37 | public List getInterfaces() { 38 | return interfaces; 39 | } 40 | 41 | public void setInterfaces(List interfaces) { 42 | this.interfaces = interfaces; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return ip + ":" + port; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/common/zk/InfoCallBack.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.common.zk; 2 | 3 | import java.util.List; 4 | 5 | public interface InfoCallBack { 6 | public void getLastList(List lists); 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/common/zk/ZkUtil.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.common.zk; 2 | 3 | import static rpc.xp.common.CommonContext.ZK_TIMEOUT; 4 | 5 | import java.util.List; 6 | import java.util.concurrent.CountDownLatch; 7 | 8 | import org.apache.zookeeper.CreateMode; 9 | import org.apache.zookeeper.KeeperException; 10 | import org.apache.zookeeper.WatchedEvent; 11 | import org.apache.zookeeper.Watcher; 12 | import org.apache.zookeeper.ZooDefs; 13 | import org.apache.zookeeper.ZooKeeper; 14 | import org.apache.zookeeper.data.Stat; 15 | 16 | public class ZkUtil { 17 | private ZooKeeper zk; 18 | 19 | public ZkUtil(String address) { 20 | 21 | final CountDownLatch latch = new CountDownLatch(1); 22 | try { 23 | zk = new ZooKeeper(address, ZK_TIMEOUT, new Watcher() { 24 | @Override 25 | public void process(WatchedEvent event) { 26 | if (event.getState() == Event.KeeperState.SyncConnected) { 27 | latch.countDown(); 28 | } 29 | } 30 | }); 31 | latch.await(); 32 | } catch (Exception e) { 33 | e.printStackTrace(); 34 | } 35 | 36 | } 37 | 38 | public void create(String path, byte[] datas) { 39 | try { 40 | zk.create(path, datas, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); 41 | } catch (Exception e) { 42 | e.printStackTrace(); 43 | } 44 | } 45 | 46 | public void CreateIfNotExist(String path) { 47 | try { 48 | Stat s = zk.exists(path, false); 49 | if (s == null) { 50 | zk.create(path, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); 51 | } 52 | } catch (Exception e) { 53 | e.printStackTrace(); 54 | } 55 | } 56 | 57 | public byte[] getData(String path) throws Exception { 58 | return zk.getData(path, false, null); 59 | } 60 | 61 | public List getInofAndWatcher(final String path, final InfoCallBack callBack) throws Exception { 62 | List nodeList = zk.getChildren(path, new Watcher() { 63 | @Override 64 | public void process(WatchedEvent event) { 65 | if (event.getType() == Event.EventType.NodeChildrenChanged) { 66 | try { 67 | List nodeList = zk.getChildren(path, false); 68 | callBack.getLastList(nodeList); 69 | } catch (Exception e) { 70 | e.printStackTrace(); 71 | } 72 | 73 | } 74 | } 75 | }); 76 | return nodeList; 77 | 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/server/Invoker.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.server; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Set; 6 | 7 | public class Invoker { 8 | private static Map services = new HashMap<>(); 9 | 10 | public static void put(Object value) { 11 | Class[] interfaces = value.getClass().getInterfaces(); 12 | for(Class interfaceTmp:interfaces){ 13 | services.put(interfaceTmp.getName(), value); 14 | } 15 | 16 | } 17 | 18 | public static Object getService(String key) { 19 | return services.get(key); 20 | } 21 | 22 | public static Set getServices(){ 23 | return services.keySet(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/server/RequestHandler.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.server; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.channel.SimpleChannelInboundHandler; 7 | import rpc.xp.common.RpcRequest; 8 | import rpc.xp.common.RpcResponse; 9 | 10 | public class RequestHandler extends SimpleChannelInboundHandler { 11 | 12 | @Override 13 | protected void channelRead0(ChannelHandlerContext ctx, RpcRequest msg) throws Exception { 14 | Object service = Invoker.getService(msg.getClassName()); 15 | Method declaredMethod = service.getClass().getDeclaredMethod(msg.getMethodName(), msg.getParameterTypes()); 16 | Object invoke = declaredMethod.invoke(service, msg.getArgs()); 17 | RpcResponse response = new RpcResponse(); 18 | response.setId(msg.getId()); 19 | response.setResult(invoke); 20 | ctx.channel().writeAndFlush(response); 21 | } 22 | 23 | @Override 24 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 25 | ctx.channel().close(); 26 | } 27 | 28 | @Override 29 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 30 | ctx.channel().close(); 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/server/Server.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.server; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.Channel; 5 | import io.netty.channel.ChannelFuture; 6 | import io.netty.channel.ChannelInitializer; 7 | import io.netty.channel.ChannelPipeline; 8 | import io.netty.channel.EventLoopGroup; 9 | import io.netty.channel.nio.NioEventLoopGroup; 10 | import io.netty.channel.socket.nio.NioServerSocketChannel; 11 | import rpc.xp.common.RequestDecoder; 12 | import rpc.xp.common.ResponseEncoder; 13 | 14 | public class Server { 15 | public static void bind(int port) throws InterruptedException { 16 | EventLoopGroup boss = new NioEventLoopGroup(); 17 | EventLoopGroup worker = new NioEventLoopGroup(); 18 | 19 | ServerBootstrap server = new ServerBootstrap(); 20 | server.group(boss, worker).channel(NioServerSocketChannel.class) 21 | .childHandler(new ChannelInitializer() { 22 | 23 | @Override 24 | protected void initChannel(Channel channel) throws Exception { 25 | ChannelPipeline pipeline = channel.pipeline(); 26 | pipeline.addLast(new RequestDecoder()); 27 | pipeline.addLast(new ResponseEncoder()); 28 | pipeline.addLast(new RequestHandler()); 29 | } 30 | 31 | }); 32 | ChannelFuture sync = server.bind(port).sync(); 33 | sync.channel().closeFuture().sync(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/rpc/xp/server/zk/Publisher.java: -------------------------------------------------------------------------------- 1 | package rpc.xp.server.zk; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | 5 | import rpc.xp.common.CommonContext; 6 | import rpc.xp.common.ServiceInfo; 7 | import rpc.xp.common.zk.ZkUtil; 8 | 9 | public class Publisher { 10 | 11 | private ZkUtil zkUtil; 12 | 13 | public Publisher(String address) { 14 | zkUtil = new ZkUtil(address); 15 | zkUtil.CreateIfNotExist(CommonContext.PATH); 16 | } 17 | 18 | public void addService(ServiceInfo info) { 19 | zkUtil.create(CommonContext.PATH + "/" + info.toString(), JSONObject.toJSONString(info).getBytes()); 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/com/xp/service/ITest.java: -------------------------------------------------------------------------------- 1 | package com.xp.service; 2 | 3 | public interface ITest { 4 | public String getMessage(); 5 | } 6 | -------------------------------------------------------------------------------- /src/test/java/com/xp/service/TestImpl.java: -------------------------------------------------------------------------------- 1 | package com.xp.service; 2 | 3 | public class TestImpl implements ITest { 4 | 5 | @Override 6 | public String getMessage() { 7 | 8 | return "hello"; 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/test/java/rpc/test/RpcClient.java: -------------------------------------------------------------------------------- 1 | package rpc.test; 2 | 3 | import com.xp.service.ITest; 4 | 5 | import rpc.xp.client.ProxyInterface; 6 | import rpc.xp.client.zk.Observer; 7 | 8 | public class RpcClient { 9 | 10 | public static void main(String[] args) { 11 | new Observer("127.0.0.1:2181"); 12 | ITest proxy = ProxyInterface.getProxy(ITest.class); 13 | String message = proxy.getMessage(); 14 | System.out.println(message); 15 | 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/rpc/test/RpcServer.java: -------------------------------------------------------------------------------- 1 | package rpc.test; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.xp.service.ITest; 7 | import com.xp.service.TestImpl; 8 | 9 | import rpc.xp.common.ServiceInfo; 10 | import rpc.xp.server.Invoker; 11 | import rpc.xp.server.Server; 12 | import rpc.xp.server.zk.Publisher; 13 | 14 | public class RpcServer { 15 | 16 | public static void main(String[] args) throws InterruptedException { 17 | ITest test= new TestImpl(); 18 | Invoker.put(test); 19 | List list = new ArrayList(Invoker.getServices()); 20 | ServiceInfo info = new ServiceInfo("127.0.0.1", 6161, list); 21 | Publisher pub = new Publisher("127.0.0.1:2181"); 22 | pub.addService(info); 23 | 24 | 25 | 26 | Server.bind(6161); 27 | 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/rpc/test/ZkTest.java: -------------------------------------------------------------------------------- 1 | package rpc.test; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.locks.LockSupport; 6 | 7 | import org.junit.Test; 8 | 9 | import rpc.xp.client.zk.Observer; 10 | import rpc.xp.common.ServiceInfo; 11 | import rpc.xp.server.zk.Publisher; 12 | 13 | public class ZkTest { 14 | 15 | @Test 16 | public void test() { 17 | 18 | new Observer("127.0.0.1:2181"); 19 | LockSupport.park(); 20 | } 21 | 22 | @Test 23 | public void publish() { 24 | List list = new ArrayList(); 25 | list.add("ggg"); 26 | ServiceInfo info = new ServiceInfo("127.0.0.1", 5000, list); 27 | 28 | Publisher pub = new Publisher("127.0.0.1:2181"); 29 | pub.addService(info); 30 | LockSupport.park(); 31 | } 32 | 33 | } 34 | --------------------------------------------------------------------------------