前言
最近在学习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...