问题:
在项目配置中skywalking的发现skywalking监控使用hessian协议的dubbo框架调用链会断裂。
原因
通过查看skywalking源码发现:dubbo中的dubbo协议是消费者和生产者使用长连接进行数据传输,而hessian协议底层是通过http方式进行数据传输。dubbo协议可以通过RpcContext
上下文进行隐式传参,而hessian不可以。skywalking的dubbo插件正式利用了dubbo隐式传参将traceId进行跨进程传输,才保证了调用链不会断。
解决方案:
废话不多说,直接上源码改源码。
- 首先看下skywalking中的dubbo插件的代码实现,如图-1所示,源码使用的是拦截dubbo中的
MonitorFilter
这个类中的invoke
方法。具体如图2所示,通过获取dubbo的上下文RpcContext
先对消费者调用之前加入sky walking的跨进程协议header信息sw:traceId
,然后到生产者取出。
图-1.png
图-2.png - 通过源码可以看出,插件是使用的是dubbo的上下文
RpcContext
进行隐式传参,可是hessian协议就是不行,不止是hessian协议,通过dubbo源码可以发现dubbo使用WebService,Rest等待协议也不行。这里我仅仅验证了hessian,解决hessian隐式传参通过查资料看hessian源码发现有两种方式:- 使用http头信息传参
- hessian多序列化反序列化一个参数
- 这里我使用的是通过http头信息进行传参,在hessian客户端调用前在头信息中植入skywalking的
sw
,然后在服务端从头信息中取出sw
放入dubbo的RpcContext
对象中。- 客户端拦截hessian的
HessianProxy
中的addRequestHeaders
方法,具体实现如图-3所示。
图-3 - 服务端拦截
HessianHandler
中的handle
方法,注意HessianHandler
是HessianProtocol
的私有类,得使用HessianProtocol$HessianHandler
类名关联,具体实现如图-4所示。
图-4.png
- 客户端拦截hessian的
结论
通过以上方式进行对hessian协议连上链路,其实dubbo其他非dubbo协议可以通过类似方式进行重新连上链路。
网友评论