分布式中的rpc调用

RPC场景和过程

在微服务环境下,存在大量的跨 JVM 进行方法调用的场景,如下图:
在这里插入图片描述
具体到某一个调用来说,希望 A 机器能通过网络,调用 B 机器内的某个服 务方法,并得到返回值:
在这里插入图片描述

RPC 的实现切入口

从本质上来讲,某个 jvm 内的对象方法,是无法在 jvm 外部被调用的

好在 java 中的对象方法的调用,还有反射模式的调用:

public class InvokeUtils {

    public static Object call(Object target,String methodName,Class [] argTypes,Object[]args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method method = target.getClass().getMethod(methodName, argTypes);
        return method.invoke(target,args);
    }


    public static Object call(Map<String,String> info, ApplicationContext ctx){
        String targetStr = info.get("target");
        String methodName = info.get("methodName");
        String arg = info.get("arg");

        try {
            return call(ctx.getBean(targetStr),methodName,new Class[]{String.class},new Object[]{arg});
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return null;
    }

}
public static void main(String[] args) {

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ProviderConfig.class);
        ctx.start();
        Map<String,String> info = new HashMap<>();
        info.put("target","orderServiceImpl");
        info.put("methodName","getDetail");
        info.put("arg","1");

        Object result = InvokeUtils.call(info, ctx);
        System.out.println("测试InvokeUtils.call调用功能,调用结果"+result);

    }

只要谁告诉我了反射需要信息,target/method/arg,我就能调用本地的任何对象方法

网络通信传递反射信息

网络通信的方法很多,如 http/rmi/webservice 等等,我们只需要选用任 意一种即可,为简便起见,我们选用 jdk 的 rmi 方式,其使用方式如下:

服务端

只需要将实例绑定注册到指定的 URL 和 port 上,远程即可调用此实例

public interface InfoService extends Remote {
    String RMI_URL = "rmi://127.0.0.1:9080/InfoService";
    int port = 9080;
    Object passInfo(Map<String,String> info) throws RemoteException;
}

public class InfoServiceImpl extends UnicastRemoteObject implements InfoService {

    static AnnotationConfigApplicationContext ctx;
    static {
        ctx = new AnnotationConfigApplicationContext(ProviderConfig.class);
        ctx.start();

    }
    public InfoServiceImpl() throws RemoteException {
        super();
    }

    @Override
    public Object passInfo(Map<String, String> info)  {
        //反射调用
        Object result = InvokeUtils.call(info, ctx);
        return result;
    }
}

	
 public static void main(String[] args) {

        try {
            //注冊通讯端口
            InfoService infoService = new InfoServiceImpl();
            LocateRegistry.createRegistry(InfoService.port);
            Naming.bind(InfoService.RMI_URL, infoService);
            System.out.println("初始化rmi绑定");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (AlreadyBoundException e) {
            e.printStackTrace();
        }

    }

客户端
RMI 远程通过 URL 连接并调用

public static void main(String[] args) {
        InfoService infoService = null;
        try {
            infoService = (InfoService) Naming.lookup(InfoService.RMI_URL);

            OrderService service = getService(infoService);
            OrderEntity result = service.getDetail("1");
            System.out.println(result);
        } catch (NotBoundException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }


    public static OrderService getService(InfoService infoService){
        OrderService service = new OrderServiceImpl(){
            @Override
            public OrderEntity getDetail(String id) {
                Map<String,String> info = new HashMap();
                info.put("target","orderServiceImpl");
                info.put("methodName","getDetail");
                info.put("arg",id);

                OrderEntity result = null; try {
                    result = (OrderEntity)infoService.passInfo(info); } catch (RemoteException e) {
                    e.printStackTrace(); }
                return result;
            }
        };

        return service;
    }

在这里插入图片描述

至此,已经实现了通过 RMI 跨机器传递 target/method/arg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值