专栏首页服务端技术杂谈dubbo源码学习笔记----RPC

dubbo源码学习笔记----RPC

RpcContext

整个RpcContext通过ThreadLocal维持。

public class RpcContext {    private static final ThreadLocal<RpcContext> LOCAL = new ThreadLocal<RpcContext>() {
        @Override        protected RpcContext initialValue() {            return new RpcContext();
        }
    };    private final Map<String, String> attachments = new HashMap<String, String>();    private final Map<String, Object> values = new HashMap<String, Object>();    private Future<?> future;    private List<URL> urls;    private URL url;    private String methodName;    private Class<?>[] parameterTypes;    private Object[] arguments;    private InetSocketAddress localAddress;    private InetSocketAddress remoteAddress;
    @Deprecated    private List<Invoker<?>> invokers;
    @Deprecated    private Invoker<?> invoker;
    @Deprecated    private Invocation invocation;

通过isProviderSide,isConsumerSide标记Context属于服务提供方还是服务使用方。

通过Future从Context中获取异步调用结果:

    public <T> Future<T> asyncCall(Callable<T> callable) {        try {            try {
                setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());                final T o = callable.call();                //local invoke will return directly
                if (o != null) {
                    FutureTask<T> f = new FutureTask<T>(new Callable<T>() {                        public T call() throws Exception {                            return o;
                        }
                    });
                    f.run();                    return f;
                } else {

                }
            } catch (Exception e) {                throw new RpcException(e);
            } finally {
                removeAttachment(Constants.ASYNC_KEY);
            }
        } catch (final RpcException e) {            return new Future<T>() {                public boolean cancel(boolean mayInterruptIfRunning) {                    return false;
                }                public boolean isCancelled() {                    return false;
                }                public boolean isDone() {                    return true;
                }                public T get() throws InterruptedException, ExecutionException {                    throw new ExecutionException(e.getCause());
                }                public T get(long timeout, TimeUnit unit)
                        throws InterruptedException, ExecutionException,
                        TimeoutException {                    return get();
                }
            };
        }        return ((Future<T>) getContext().getFuture());
    }

服务调用

public class RpcInvocation implements Invocation, Serializable {    private static final long serialVersionUID = -4355285085441097045L;    private String methodName;    private Class<?>[] parameterTypes;    private Object[] arguments;    private Map<String, String> attachments;    private transient Invoker<?> invoker;

代理调用

public class JavassistProxyFactory extends AbstractProxyFactory {    @SuppressWarnings("unchecked")
    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {        return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
    }

    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {        // TODO Wrapper cannot handle this scenario correctly: the classname contains '$'
        final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);        return new AbstractProxyInvoker<T>(proxy, type, url) {            @Override
            protected Object doInvoke(T proxy, String methodName,                                      Class<?>[] parameterTypes,                                      Object[] arguments) throws Throwable {                return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
            }
        };
    }

}


public class JdkProxyFactory extends AbstractProxyFactory {    @SuppressWarnings("unchecked")
    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new InvokerInvocationHandler(invoker));
    }

    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {        return new AbstractProxyInvoker<T>(proxy, type, url) {            @Override
            protected Object doInvoke(T proxy, String methodName,                                      Class<?>[] parameterTypes,                                      Object[] arguments) throws Throwable {                Method method = proxy.getClass().getMethod(methodName, parameterTypes);                return method.invoke(proxy, arguments);
            }
        };
    }

}

RedisProtocol

比较有意思,是通过对invocation.Arguments作为key放到redis中取值,将值反序列化出来作为执行结果。

          resource = jedisPool.getResource();                        if (get.equals(invocation.getMethodName())) {                            if (invocation.getArguments().length != 1) {                                throw new IllegalArgumentException("The redis get method arguments mismatch, must only one arguments. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url);
                            }                            byte[] value = resource.get(String.valueOf(invocation.getArguments()[0]).getBytes());                            if (value == null) {                                return new RpcResult();
                            }
                            ObjectInput oin = getSerialization(url).deserialize(url, new ByteArrayInputStream(value));                            return new RpcResult(oin.readObject());

本文分享自微信公众号 - 服务端技术杂谈(ITIBB2014)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-01-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • spring boot整合hessian

    首先添加hessian依赖 <dependency> <groupId>com.caucho</groupId> <artifactId>he...

    春哥大魔王
  • BeeGo web搭建–环境配置

    学习一个新框架,对于有较多编程经验的开发人员写代码不是问题,但是往往卡在了环境配置或者第一段Hello World,今天介绍一下Beego web框架的搭建和环...

    春哥大魔王
  • 基于Servlet3.0异步特性实现请求鉴权与转发

    项目背景 在多个内网系统之上,增加一个网关服务,统一对第三方应用进行鉴权与认证,方可对内部资源服务进行访问,网关服务主要起到鉴权认证,请求转发主要借助Servl...

    春哥大魔王
  • Java 编程技巧之数据结构

    编写代码的"老司机"也是如此,"老司机"之所以被称为"老司机",原因也是"无他,唯手熟尔"。编码过程中踩过的坑多了,获得的编码经验也就多了,总结的编码技巧也就更...

    用户1516716
  • Java高并发之设计模式

    原文出处:http://www.yund.tech/zdetail.html?type=1&id=34e52a515cd0e4d120255c90f33396a...

    大道七哥
  • Java 编程技巧之数据结构

    编写代码的"老司机"也是如此,"老司机"之所以被称为"老司机",原因也是"无他,唯手熟尔"。编码过程中踩过的坑多了,获得的编码经验也就多了,总结的编码技巧也就更...

    吴延宝
  • Spring Security项目第三方登陆(四)

    楠楠
  • SpringMVC教程2[处理及响应请求]

    此时,在浏览器端请求/test1接口,springmvc会默认去查找和方法同名的页面作为方法的视图返回。 如果确实不需要该方法返回页面,可以使用@Respons...

    用户4919348
  • java 原型模式之深拷贝和浅拷贝

    用户5166556
  • 性能优化-测试for循环中的反射操作

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明...

    cwl_java

扫码关注云+社区

领取腾讯云代金券