您的位置:首页 > 运维架构

201207.24.bops操作者id丢失问题排查过程

2012-07-24 14:24 309 查看
背景:

运营反馈在进入页面操作时,修改会员密码等操作会提示操作者id丢失等问题。

代码实现原理:

查看代码,发现是从cookie中获取的操作者id通过log4j的MDC进行上下文传递,写入时正常,但是获取时出现信息丢失。

技术背景:

MDC的实现原理是threadlocal获取上下文,所以在非误操作情况下,在这个线程中的信息是不会丢失的

分析过程:

1.模拟运营操作:发现部分操作成功,部分操作失败;很容易让人联想到是因为个别会员导致的,也是一开始被迷惑了(线上是一个集群),走了不少弯路

2.模拟环境:单独启动一个应用,发现没有失败过,从cookie到MDC的写入以及读出,完全正确,现场无法模拟,实在难以追踪,中断一段时间

后来有位wlb同事刚好搭建了环境,必现这个问题,开始着手排查

3.模拟异常请求:分析请求过程,发现cookie到MDC正常,但是读取失败,想必是代码问题。

4.综上几个,初步定论,该实现与代码部署相关,在特定一些机器下部署,代码不会出现问题且运行正常;但是在其他机器下部署,必然出现问题。

这种问题比较可能是跟类加载有关。

5.分析整体代码结构:

调用点:





实现:





说明下:

代码自己封装了jakarta.commons.logging.xxx.jar,getFactory()就是通过jakarta.commons.logging的实现去知道具体的log,然后又由自定义的Logger去包装了一下Log(只包装非log4j实现,MDC依赖log4j)。自己封装logger为了暴露MDC和NDC的接口,至于为什么要这么风封装,这里不深纠了,毕竟代码比较古来。(个人不太喜欢这种封装,完全可以直接用jakarta.commons.logging)。

再来看下getFactory()实现,这个直接关系到具体的代码。网上能找到一些说明,查找具体Factory实现的类,顺序:

读取:commons-logging.properties 的org.apache.commons.logging.LogFactory

系统传入的org.apache.commons.logging.LogFactory属性

类路径下的META-INF/services/org.apache.commons.logging.LogFactory文件

默认实现org.apache.commons.logging.impl.LogFactoryImpl

系统没有传入任何东西,默认是使用的是第三种,分析代码,类似路径的jar包有三个,并且都在war的lib下,具体如下:

META-INF/services/org.apache.commons.logging.LogFactory:

jmemory-1.0-SNAPSHOT.jar

com.alibaba.common.logging.spi.GenericLoggerFactory

toolkit.common.logging-1.0.jar

com.alibaba.common.logging.spi.GenericLoggerFactory

org.slf4j.jcl104-over-slf4j-1.5.6.jar

org.apache.commons.logging.impl.SLF4JLogFactory

前两个还好实现是两套代码,但代码一模一样,咳

但是第三个的实现完全不同,实现是SLF4JLogFactory工厂。

jvm在类加载阶段读取具体的配置,由于lib下读取的顺序是jboss控制,并且和机器有关,导致读取时有些读取到GenericLoggerFactory,产生的log为log4j,能获取到MDC,有些SLF4JLogFactory,产生的log为org.apache.commons.logging.impl.SLF4JLocationAwareLog,该log并非log4j实现,在封装logger时,采用了LoggerWrapper,里面的MDC实现为空实现,导致信息没有记录。

直接诱因:odin引入的

<groupId>com.xxxxx.external</groupId>

<artifactId>org.slf4j.jcl104-over-slf4j</artifactId>

解决:

1.逐出org.slf4j.jcl104-over-slf4j,直接但不彻底

2. bops由于日志系统太多,有log4j(web),slf4j(task),但是包打成一个,在加载时会出现一些不可预期的结果,建议梳理bops。

最好能把MDC全部替换为threadlocal,这样不依赖于任何日志系统,原先的使用方式已经不适合了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: