Debug时加的观察变量影响了debug
一、问题描述
有这样一个流程:从FTP上下载文件后,会根据文件名读取缓存实现防重,其中缓存读取到的值会写入Camel的exchange,exchange.getIn().setBody(cacheValue);
。
但是,通过日志观察该Body是一串无规律的字符,类似My8+PFNEMvPjxSRU1BUksxLz48UkMRT48TUFUTlI+QVBHTTA0OC02PC9NQVROUj48TUFLVFg+57qi6Imy5Ki75aSn5Y+36LSt54mp6KJWkVTX0RBVEE+PFNJWkU+MDAwPC9VNQVJLMi8+PFJFTUFSSzMvPjxSRU1BUks0Lz48L1NJWkVTX0RBVEE+PC9NQUlOX1RBQkxFPjwvUk9PTUFJTl9UQUJTSVpFPjxXRUlHSFQvPjxMRU5HVEgvPjxXSURUSC8+PEhFSUdIVC8+PElOQ0FTRU1FTlQvPjxFQU5VUKLPVD4D488Uk9PVC9NQUtUW
。
二、排查路径
1)测试缓存值非null情况
若缓存值非null,则body显示正常
若缓存不存在,Body显示为不规律字符串
2)查看运行日志
发现缓存节点执行结束时,*exchange.getIn.setBody(cacheValue)*的cacheValue变量确实是null。
但是缓存节点之后的日志节点打印的日志中,Body却是不规律字符串
3)远程断点Debug
- 断点设置在get-cache节点结束位置
- 验证了cacheValue确实是null
- 增加自定义变量,类似ElUtils.evaluate(“${body}”, exchange, Object,class),观察到Body为字符串(此时产生了困惑,明明写入的是null,但是获取的body却非空)
- 根据断点时添加的观察变量,发现exchange.getIn()返回的是org.apache.camel.component.file.GenericFileMessage。
- 查看源码org.apache.camel.component.file.GenericFileMessage#setBody
- 源码里没有对null做特殊处理
1 | public abstract class MessageSupport implements Message, CamelContextAware, DataTypeAware { |
- 断点设置在setBody方法里
- 观察变量this.body值,发现this.body,确实设为null
- 增加自定义变量,通过*ElUtils.evaluate(“${body}”, exchange, Object,class)*获取body值,发现body设为null后,然后又变为字符串
- 怀疑是el表达式子,最终调用的getBody方法重置了Body。
- 查看org.apache.camel.component.file.GenericFileMessage#getBody()
- 发现GenericFileMessage对null做了特殊处理,为空时会根据file重建body。
1 | public abstract class MessageSupport implements Message, CamelContextAware, DataTypeAware { |
三、总结
此处问题的原因是,流程中FTP构造的Exchange中的message类型为GenericFileMessage,当该类型的message的body属性为空时,调用getBody方法会根据文件内容重置body属性。所以,我们看到哪些混乱的字符串实际上是FTP节点下载的文件内容的一种序列化表现。
总之,在Debug时你定义的观察变量有可能在未知处默默修改系统的运行变量,导致Debug时无法复现Run时的问题。如果有些变量因你观察而变化时,你就要评估下你的自定义变量是否隐式调用了一些修改类方法。