手写RPC框架(三)实现服务注册
手写RPC框架(三)实现服务注册
RPC框架一般由服务端,消费端,注册中心三部分组成。注册中心负责持久化服务名称,IP地址以及端口等。本次只实现简单的服务注册功能。
-
实现服务注册功能
public class ServiceRegister { //负责存储服务列表 private static List
此时消费端获取服务类时直接在serviceList中获取
-
服务端
public Object getService(Class servicesClass){ for(Object obj:serviceList){ boolean isFather=servicesClass.isAssignableFrom(obj.getClass()); if(isFather){ return obj; } } return null; }
将服务端继承Runable接口,在发布一个RPC服务时,直接实例化该线程并启动该线程。
public class Provider implements Runnable{ private Socket client=null; private List
-
进行服务注册
public class RpcBootstrap { public static void main(String[] args) throws IOException { Calculator calculator=new CalculatorImpl(); ServiceRegister.export(8081,calculator); } }
-
消费端使用ip,port作为参数
public class ConsumerProxy implements InvocationHandler { private String ip; private int port; public ConsumerProxy(String ip, int port) { this.ip = ip; this.port = port; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Exception { Socket socket = new Socket(ip,port); ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream()); RpcRequest rpcRequest = new RpcRequest(proxy.getClass().getInterfaces()[0], method.getName(), method.getParameterTypes(), args); objectOutputStream.writeObject(rpcRequest); ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream()); return inputStream.readObject(); } }
-
获取代理对象
public static
T getService(Class clazz,String ip,int port){ ConsumerProxy consumerProxy=new ConsumerProxy(ip,port); return (T)Proxy.newProxyInstance(ConsumerApp.class.getClassLoader(),new Class<?>[] {clazz},consumerProxy); } -
测试程序
public static void main(String[] args) { Calculator calculator= ConsumerApp.getService(Calculator.class,"127.0.0.1",8081); int res=calculator.add(100,86); System.out.println(res); }
Proxy.newProxyInstance
这个函数是用来返回代理对象的,我发现使用ConsumerApp.class.getClassLoader()
和Calculator.class.getClassLoader()
作为第一个参数都是可以的,通过debug发现这两个类的类加载器一致,
java在运行程序时,并不是一次性加载所有的类,而是把基础类加载到jvm中,再加载其他的类来节省开销。类加载是指JVM中加载class文件的过程(加载→验证→准备→解析→初始化),所有通过正常双亲委派模式的类加载器加载的classpath下的和ext下的所有类在方法区都是同一个类,堆中的Class实例也是同一个。
JDK 默认提供了如下几种ClassLoader
- Bootstrp loader
- ExtClassLoader
- AppClassLoader