dahezi2
dahezi2
  • 发布:2020-07-10 16:05
  • 更新:2020-07-10 16:05
  • 阅读:1072

微服务下基于sleuth的参数透传功能探索

分类:uni小程序sdk
  1. 需求
    微服务环境,有A,B,C,D四个服务,调用关系为:A->B->C->D。用户在A的页面选择当前“语言”环境为“英文”,在某些业务场景下,其它几个服务需获取到这个“语言”信息。

  2. 分析
    这个需求还是很简单的,类似于“击鼓传花”:当前服务从上一个服务中获取参数,并传给下一个服务。个人感觉基本上所有的RPC框架都会遇到这个问题,只是以前SOA架构下,服务层级比较少,将“语言”、“登陆”等附加信息放在参数列表中并不会带来太多工作量,所以这个问题并不是太突出。而引入了微服务架构思想后,服务调用层级急剧增长,这就需要一个更加优雅的方式来解决附加信息的传递问题。

3.方案探索
3.1 方案一:参数放在接口参数列表中
3.1.1 优点:
思路简单,开发没有学习成本

3.1.2 缺点:
代码高度耦合:附加信息却要每个接口都显式维护
升级困难:如果将来再加一个参数,所有层级的接都要改动
引起迷惑:如果B服务的逻辑不需要“语言“参数,但是因为D需要,它也必须维护
太傻了,Big不够
3.1.3 思考:
微服务之间绝大多数情况是通过HTTP调用的,HTTP的header中也可以放参数信息。这样,接口参数中就不用维护这些附加信了。

3.2 方案二:参数放在httpRequest的header中
3.2.1 实现:
自定义一个Filter,获取Request中自己需要的附加信息
将这些信息放入ThreadLocal中
实现feign.Client(这里先忽略RestTemplate)的execute()方法,将附件信息在调用下一层服务前塞入request的header中
3.2.2 优点:
参数解耦

3.2.3 缺点:
如果B在获取到附加信息后,新起了一个线程”T1“来调用服务C,这时T1就无法从ThreadLocal拿到附加信息了

3.2.4 思考:
如果我知道怎么用无侵入的方式,在当前线程”T”创建子孙线程”T1”、”T1-1”时,将数据传给后代,就能解决这个问题了
微服务调用链框架Sleuth的核心功能即是跟踪一次请求从A到D的全过程,它肯定支持多线程调用下的traceId的传递。因此,我可以复用Sleuth的相关功能夹带私货
3.3 方案三:修改Sleuth源码,将附加信息跟着TraceId一起往后传递
3.3.1 优点:
原理简单,不用考虑底层实现
不用考虑兼容性等问题,Sleuth都已经实现好
快(对,就是这一个字)
3.3.2 缺点:
维护困难,很容易忘记以前修改了哪些地方,更别提移交给别人维护了
升级困难,以后每次Spring或者Sleuth升级,都要重新下载源码修改
3.3.3 思考:
目前获取参数的问题解决了,用Filter,只剩下保存并传给下一层的问题
既然Sleuth已经解决了多线程下traceId的传递问题,那我就直接用traceId来解决我的问题
3.4 方案四:充分利用traceId
3.4.1 实现:
自定义Filter(优先级要低于TraceFilter,因为你要获取TraceFilter里的traceId),拿到traceId和附加信息后,将它们存在本地缓存中,traceId为key,附加信息为value
参考方案二的实现3。重写execute()方法,获取当前线程的traceId(这个Sleuth有接口,不再介绍),然后再通过traceId去本地缓存中拿到附加信息,放进Request的header中
3.4.2 优点:
拥有上述方案所有的优点
解决上述方案所有缺点
3.4.3 缺点:http://springcloud.cn/view/41

0 关注 分享

要回复文章请先登录注册