java动态代理实现基于HTTP协议的远程调用

背景

很多应用在进行多租户改造的时候,需要将原来的单体应用拆分成一个manager和多个agent,manager部署在公司,agent部署在租户的环境,manager通常用于调度转发、业务管理,agent主要是在客户环境中承担具体业务处理,诸如对接大数据组件,承担计算任务等。

而多数情况下manager和agent之间是跨公网调用,不是处于同一内网环境通过服务调用的。而真正可以处理具体业务是在agent,所以在跨公网的条件下基于tcp协议如RMI是行不通的,所以要进行restful的改造。

为了尽量不影响现有应用代码,做了如下改造:agent抽象出api接口,manager只需要依赖相应的agent暴露的api接口即可完成调度转发。

我们要做的就是基于http的远程调用。

使用场景

跨公网的远程调用,不支持tcp协议。

方案

参考mybaties的实现方法考虑使用代理模式,在调用端只有api接口,接口的实现是被代理掉的,在项目启动时会为每一个配置的接口生成一个java动态代理,这个动态代理做的事情就是将方法需要的参数都序列化,通过http request传给agent,然后agent执行并返回结果。本质是利用jdk动态代理将方法的调用转化成http请求调用。

实现

1:首先获取所有需要代理的类(实现动态代理时构造方法获取每一个类的method),为每一个需要代理的类注册实例

2: 在实现动态代理的invoke方法内,通过抽象方法HttpRequestService,设置http请求转发到agent通用的api接口中,将agent所需要的,诸如method,class名称,请求参数等,序列化传过去。

HttpRpcInvocator(Class<?> clazz, HttpRpcService httpRpcService) {
        this.clazz = clazz;
        this.httpRpcService = httpRpcService;
        for(Method method: clazz.getMethods()) {
            String methodName = method.getName();
            if (!methodName.equals("equals") &&! methodName.equals("hashCode") && !methodName.equals("clone") && !methodName.equals("toString")) {
                methodSet.add(method);
            }
        }
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        if (method == null || !methodSet.contains(method)) {
            StringBuilder methods = new StringBuilder();
            methods.append("[");

            Iterator it = methodSet.iterator();
            while (it.hasNext()) {
                methods.append(((Method)it.next()).getName()).append(",");
            }
            methods.deleteCharAt(methods.lastIndexOf(","));

            methods.append("]");
        }
        return httpRpcService.httpRequest(method, args);
    }


    public void httpRequest(String domain, HttpRpcParam param) {
        // manager调用agent通用http接口,封装请求param,将agent所需要的,诸如method,class名称,请求参数等,序列化传过去
    }

2:在agent实现一个通用的api接口,用以接收所有来自master的请求,然后通过反射获取结果,最后将结果返回给manager,manager序列化返回结果。

 @RequestMapping(value = "/api", method = RequestMethod.POST, produces = (MediaType.APPLICATION_OCTET_STREAM_VALUE))
 private ResponseEntity<Object> entrance(HttpServletRequest request) {

 // agent通用api接口,接收所有来自manager的请求,然后通过反射获取结果,最后将结果返回给manager
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值