前言

这两天我在升级ES版本,把我们团队的项目升级测试完了,准备开始升级其他团队开发的另外一个项目。

遇到了一个日志消失的问题,拿出来跟大家一起分享一下,希望对你会有所帮助。

案发现场

我最近接到一个新任务,要去升级另外一个项目的ES版本。

由于之前升级我们团队的ES项目时,踩了很多坑,我专门总结了一个文档,本以为拿着这个文档去升级那个项目中的ES简直是小case。

在加上这个新项目中,使用ES仅仅是为了记录用户的请求日志,比如:请求地址、请求参数、header、响应码、响应数据等等。

这是一个比较小的改动,更让我觉得,这个事情非常easy。

我按照之前整理的文档中的步骤,很快把这个项目改造完了。

这个项目是一个老项目,配置文件都写在application-xxx.yml文件中,把ES的相关配置改成最新就可以了。

然后把pom.xml文件中引用ES的jar包的版本号,由6.4.0升级到7.16.3,再把引入新jar包后,差异化的代码稍微调整一下就OK了。

还有一个地方需要修改:为了上pre时,不影响Ga,让新老ES服务器同时存在一段时间,我重新加了一套host、port和user的配置。

由于公司其他团队,还有一些项目没有升级ES,他们已经排期了后续会逐步升级的,这次我们团队和另外一个项目先上。

于是,生产环境到时候会存在新老ES同时存在的情况,一部分项目使用新的ES服务,一部分项目使用老的ES服务。

我改造完这个项目之后,编译了一下没有问题,然后部署到了dev环境,准备开始测试了。

项目部署成功了。

我在dev环境手动跑了一个job,测试ES日志写入功能是否成功时,却发现没有一条数据写入ES当中,而且发现一个非常诡异的问题:有些日志凭空消失了。

当时从Grafana的日志中查到了job开始执行的日志,但是却没有打印写ES的日志,也没有打印任何异常日志。

当时写ES的代码大概是这样的:

BulkRequest bulkRequest = new BulkRequest();
IndexRequest indexRequest = new IndexRequest(index);
indexRequest.source(JSON.toJSONString(logModel),XContentType.JSON);
bulkRequest.add(indexRequest);

try {
   BulkResponse response = esClient.bulk(bulkRequest, RequestOptions.DEFAULT);
   if(response.hasFailures()) {
     log.error("日志写入失败",e); 
   } else {
      log.info("日志写入成功");
   }
} catch(IOException e) {
  log.error("日志写入失败",e); 
}

这段代码的逻辑很简单,如果写入ES成功了,则打印成功日志。如果写入ES失败了,则打印失败日志。

但非常奇怪的是,这些日志都没有打印。

分析问题

出现这个问题,最可能的原因有两种:

  1. error级别的日志,跟info级别的日志,不在一起。
  2. 抛出的异常不是IOException。

第一种可能,很快被否定了,因为从Granfa日志中查到了其他的error日志。

只剩下第二种可能了。

我将捕获的异常从IOException改成了Exception,将异常的范围升级了。

try {
   BulkRequest bulkRequest = new BulkRequest();
   IndexRequest indexRequest = new IndexRequest(index);
   indexRequest.source(JSON.toJSONString(logModel),XContentType.JSON);
   bulkRequest.add(indexRequest);
   BulkResponse response = esClient.bulk(bulkRequest, RequestOptions.DEFAULT);
   if(response.hasFailures()) {
     log.error("日志写入失败",e); 
   } else {
      log.info("日志写入成功");
   }
} catch(Exception e) {
  log.error("日志写入失败",e); 
}

怕new IndexRequest等代码出问题,将这些代码也放到了try...catch当中了。

这样改造之后,重新部署了dev环境。

再次跑了dev环境的job,数据仍然没有写入ES,并且也没有查到相关的日志。

这就有点奇怪了。

莫非抛出的不是Exception?

我抱着试一试的心态,将捕获的异常由Exception改成了Throwable。

try {
   BulkRequest bulkRequest = new BulkRequest();
   IndexRequest indexRequest = new IndexRequest(index);
   indexRequest.source(JSON.toJSONString(logModel),XContentType.JSON);
   bulkRequest.add(indexRequest);
   BulkResponse response = esClient.bulk(bulkRequest, RequestOptions.DEFAULT);
   if(response.hasFailures()) {
     log.error("日志写入失败",e); 
   } else {
      log.info("日志写入成功");
   }
} catch(Throwable e) {
  log.error("日志写入失败",e); 
}

改造完之后,部署到了dev环境。

之后,日志中还真的出现了一个异常日志:XContextType类找不到。

但这个类在ES客户端7.16.3的版本明明是有的,为什么会报这个异常呢?

极有可能是出现了版本冲突。

后来发现,还真的出现了版本冲突,在maven工程中,6.4.0和7.16.3两个版本的jar包都存在。

终于查到原因了。

如何解决问题?

其实jar包冲突的问题,我在以往的工作中,已经解决过很多次了。

只需要在pom.xml文件中,找到相关的依赖包,使用排除掉不需要的版本号就OK了。

但我找了半天,并没有找到哪里引入ES的6.4.0的jar包。

莫非idea有缓存?

我在idea中执行了mvn clean命令,清理了一下依赖,重新导入了依赖,但6.4.0的jar包依然还在。

于是,我换了一种思路。

在父工程的pom.xml文件中的中增加了ES相关groupId、artifactId和version的声明。

然后在子工程中的中直接引入该groupId和artifactId。

这样改造之后,ES6.4.0的jar包没出现了。

这也是解决jar包冲突的一种思路。

之后,项目调整完,顺利上线了。

总结

日志消失的根本原因是:当时抛了Error而非Exception,所以并没有打印出来。

所以建议大家在使用try...catch捕获异常时,尽量在catch中捕获Throwable。

它会把Error和Exception都捕获。

我遇到的就是一个真实的教训。

之前的同事写代码不规范,把这些抛异常的代码:

indexRequest.source(JSON.toJSONString(logModel),XContentType.JSON);

没有放到try...catch代码块中,导致有些问题不能及时发现。

我们在写代码时,尽量把可能出现异常的代码,都try...catch了。

最后修改:2026 年 06 月 06 日
如果觉得我的文章对你有用,请随意赞赏