手动实现RPC远程调用

来源:互联网 发布:淘宝电风扇 编辑:程序博客网 时间:2024/04/27 01:55

java中的RPC核心思想就是:socket编程、传输Object、动态代理


package com.lala.rpc;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.net.ServerSocket;import java.net.Socket;public class RpcFramework {/** * 初始化一个服务端socket,一直监听客户端请求,当有请求时,依次读取 方法名称,方法参数类型,方法参数, * 根据这些信息在service上找到相应的method,然后,service方法上执行对应的方法,把方法返回值传输回去 * @param service 暴露的服务接口实现类 * @param port  绑定的端口 * @throws Exception */@SuppressWarnings("resource")public static void publish(final Object service, final int port)throws Exception{final ServerSocket server = new ServerSocket(port);System.out.println("rpc server is start on port : " + port);while(true){final Socket client = server.accept();new Thread(() -> {ObjectInputStream input = null;ObjectOutputStream output = null;try{input = new ObjectInputStream(client.getInputStream());output = new ObjectOutputStream(client.getOutputStream());String methodName = input.readUTF();Class<?>[] pamTypes = (Class<?>[])input.readObject();Object[] args = (Object[])input.readObject();Method method = service.getClass().getMethod(methodName, pamTypes);Object obj = method.invoke(service, args);output.writeObject(obj);}catch(Throwable e){try {output.writeObject(e);} catch (Exception e1){e1.printStackTrace();}}finally{closeStream(output);closeStream(input);closeStream(client);}}).start();}}/** * 根据host, port初始化一个socket,然后传输 方法名称,方法参数类型,方法参数,最后获取服务器返回的结果,就是方法执行的返回值 * @param clazz 调用的接口 * @param host远程服务器 * @param port  端口 * @return * @throws Exception */@SuppressWarnings("unchecked")public static <T> T reference(final Class<T> clazz, final String host, final int port)throws Exception{return (T)Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, new InvocationHandler(){public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {final Socket client = new Socket(host, port);ObjectOutputStream output = new ObjectOutputStream(client.getOutputStream());/** * 往服务端发送方法名称,参数类型,参数 */output.writeUTF(method.getName());output.writeObject(method.getParameterTypes());output.writeObject(args);ObjectInputStream input = new ObjectInputStream(client.getInputStream());try{/** * 获取服务端,方法执行的结果 */Object res = input.readObject();if(res instanceof Throwable){throw (Throwable)res;}return res;}catch(Throwable e){throw e;}finally{closeStream(input);closeStream(output);closeStream(client);}}} );}private static void closeStream(AutoCloseable stream){if(stream != null){try{stream.close();}catch(Exception e){//ignore}}}}


此处写一个测试接口:

package com.lala.rpc;public interface UserService{public String getNameById(String id);}


接口的实现类:

package com.lala.rpc;public class UserServiceImpl implements UserService {public String getNameById(String id) {return "hello " + id;}}

服务端:

package com.lala.rpc;public class Server {public static void main(String[] args) throws Exception{UserService userService = new UserServiceImpl();RpcFramework.publish(userService, 9999);}}


调用客户端:

package com.lala.rpc;public class Client {public static void main(String[] args) throws Exception{UserService userService = RpcFramework.reference(UserService.class, "127.0.0.1", 9999);System.out.println(userService.getNameById("100"));}}



7 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 ipad的按键坏了怎么办 更新ios12软件闪退怎么办 设置虚拟服务器输入不了数字怎么办 玩客云自动备份设备连接失败怎么办 3dmax文件打开失败怎么办 夏天吹空调嘴歪怎么办 燃气热水器温度调节拧不动怎么办 能率热水器震动声大怎么办 车底盘磕了漏油怎么办 法士特变速箱的随动阀漏气了怎么办 大灯随动afs失灵怎么办 2017款迈腾大灯随动故障怎么办 微信gps信号不好怎么办 苹果6s定位不准怎么办 电脑不读取u盘怎么办 注塑机上的料烤坨了怎么办 智能锁电机坏了怎么办 注塑机加热嘴内扣突了怎么办 tpu粘在螺杆上怎么办 注塑机锁模时会有射退动作怎么办 电动车刹车油泵不打油怎么办 cad转pdf颜色浅怎么办 松下多功能传真一体机卡纸怎么办 无刷电机坏了怎么办 6kv高压电机绝缘不合格怎么办? 400t油压机下降太慢怎么办 无法连线到服务器1~1怎么办? 数控车床车角度不亮怎么办 超市存包柜的票不见了怎么办 交货期来不及导致船期延误怎么办 跑1000米中途累怎么办 手指被机器压烂怎么办 机械手不能回归原点该怎么办 前缘送纸纸板翘怎么办 三菱AL 1R.2报警怎么办 工作好但领导不好伺候怎么办 孕妇憋尿憋的小腹疼怎么办 怀孕憋尿憋的小腹疼怎么办 半夜憋尿憋的小腹疼怎么办 新生儿大便次数较多怎么办 母猎生下三天没有奶怎么办