前言
最近在学习 Kafka Connect,写了个连接器的 demo。在 demo 提交了几个版本之后,忽然发现 Kafka Connect Rest API 无奈失常响应了,明明有正在运行的连接器,查问 status,竟然返回{}
问题剖析
对 Rest API 进行 debug 后,确认是有数据的,然而数据返回不到客户端,很奇怪。因为我记得之前是好用的,所以我回滚了代码版本,逐个排查之后发现当引入 Fastjson 依赖之后,会导致 Connect Rest API 不可用
如果懒一点的话,到这里就曾经完结了,间接删除 Fastjson 依赖,应用其余 Json 包。然而我很好奇,在我的了解里,Fastjson 这种库就是个工具包,如果咱们程序没有被动调用的时候,是不会对咱们产生任何影响的。
百度谷歌一通之后,束手无策之际,点开了 Fastjson 的源码包,在这里发现了 Fastjson 为 JAXRS 提供的 SPI 扩大
JAXRS:Java API for RESTful Web Services,JavaEE 提供的 Web 服务接口。Jersey 实现了 JAXRS,而 Kafka Connect 援用了 Jersey。
SPI:Service Provider Interface,是 JDK 内置的一种服务提供发现机制,能够参考我之前的博客 Java SPI 实战
关上 javax.ws.rs.ext.MessageBodyWriter
文件,能够看到提供的实现类是com.alibaba.fastjson.support.jaxrs.FastJsonProvider
,定位到FastJsonProvider
下writeTo
办法,该办法会把 object 写入到 OutputStream 中,看起来很靠谱,debug 试一下
果然,阐明 Fastjson 果然参加了 Rest API 的响应。为什么应用 Fastjson 就响应不了数据呢,看了下源码,这里要求被序列化的 Bean 必须标记 Fastjson 相干的注解,而理论的 Bean 应用的是 Jackson 的注解,所以 Fastjson 无奈序列化数据。
接下来能够依据调用栈和全局搜寻找一下,看看 FastJsonProvider 是在什么机会加载的,是否干掉他。
调用栈并没有找到什么有用的信息,通过全局搜寻 MessageBodyWriter
找到了 FastJsonProvider 的加载地位,MessageBodyFactory::initialize
上图字面意思了解,应用 injectionManager
(注入管理器),找到 MessageBodyWriter
的可用实现
这里的 customMbws
size = 2,别离是 FastJson 和 Jackson 的实现。然而 FastJson 在前,而每次须要做 JSON 序列化的时候,会遍历 writers
,如果找到反对application/json
的 MessageBodyWriter 则间接返回,所以每次应用的都是 FastJson 的实现。
至此曾经明确了,为什么 Fastjson 会影响 Kafka Connect 了,接下来就是想方法解决了
这个时候还是没有找到 Fastjson 是在哪加载的,在 Fastjson 的 wiki 中找到了些灵感,发现 Fastjson 在 Jersey 中并不是通过 SPI 的形式进行的扩大,而是通过FastJsonAutoDiscoverable
,向 Jersey 的 context 中注册FastJsonProvider
最初,咱们在 java 过程启动时指定参数 -Dfastjson.auto.discoverable=false
,禁用 FastJsonProvider
参考
https://github.com/alibaba/fa…