SOFA 源码分析 — 链路数据透传

前言

SOFA—RPC 支持数据链路透传功能,官方解释:

链路数据透传功能支持应用向调用上下文中存放数据,达到整个链路上的应用都可以操作该数据。 使用方式如下,可分别向链路的 request 和 response 中放入数据进行透传,并可获取到链路中相应的数据。

使用方式:

RpcInvokeContext.getContext().putRequestBaggage("key_request","value_request");
RpcInvokeContext.getContext().putResponseBaggage("key_response","value_response");

RpcInvokeContext.getContext().getAllRequestBaggage("key_request");
RpcInvokeContext.getContext().getAllRequestBaggage("key_response");

源码分析

从这个 4 句代码开始看。

关键类: RpcInvokeContext,该类是一个 基于ThreadLocal的面向业务开发者使用的上下文传递对象

内部维护了一个 ThreadLocal 对象。

protected static final ThreadLocal<RpcInvokeContext> LOCAL = new ThreadLocal<RpcInvokeContext>();

value 是一个 RpcInvokeContext 对象。

当调用 getContext 的时候,就会从当前线程获取 RpcInvokeContext 对象。

该类定义了以下属性:

  • boolean BAGGAGE_ENABLE 是否开启上下文透传功能,关闭后,会提高性能
  • Integer timeout 用户自定义超时时间,单次调用生效
  • String targetURL 用户自定义对方地址,单次调用生效
  • String targetGroup 用户自定义对方分组
  • SofaResponseCallback responseCallback 用户自定义Callback,单次调用生效
  • ResponseFuture<?> future
  • ConcurrentMap<String, Object> map 自定义属性
  • Map<String, String> requestBaggag 请求上的透传数据
  • Map<String, String> responseBaggage 响应上的透传数据

知道了基本的数据结构,再看看上面的几个方法:

  • putRequestBaggage()
  • putResponseBaggage()
  • getAllRequestBaggage()
  • getAllRequestBaggage()

其实都是从 Map 中获取数据,不过,貌似官方的例子有点问题,后面两个例子不对。没有 key 。待我提个 issue。

sofa-fail.png

总结

这个功能让我想到了我在公司项目中使用的 CurrentUser 功能,也是使用的 ThreadLocal,将用户的信息存在线程中,这样就不必将常用数据在方法参数中传递了,省了很多事。只不过异步的时候,可能会有点问题,需要手动将 ThreadLocal 传递到异步线程中。

不过,我没有使用手动传递,我是这么设计的:自定义线程池和线程工厂,线程工厂创建线程的时候,会将主线程的 ThreadLocal 复制到异步线程中,并自定义了线程类,在 finally 块中删除 ThreadLocal,非常完美的一个设计。这样就不必每次手动传递并手动删除了。

好了,这个功能还是很简单的。但非常实用,不过要是能加上我上面设计的那个功能就好啦! 哈哈!

作者:莫那鲁道

出处: 博客园:http://www.cnblogs.com/stateis0/
            个人博客: thinkinjava.cn

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/stateis0/p/8983551.html