欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

本周技术问题总结--2017.09.01

程序员文章站 2022-05-04 13:17:31
...

目录

 

一、idea打包关闭test

二、log4jslf4j包冲突

三、user.name配置与系统环境变量重名失效

四、jvm内存报警

 

日常工作中经常会遇到一些问题,会花大量时间去解决,但时间一长又会遗忘,以后不定期收集每周遇到问题,进行整理收集。以下是本周遇到的几个问题:

 

一、idea打包关闭test

本周项目处于调试阶段,在调试过程中经常出现数据库表里的测试数据被删、或被修改的情况。严重影响测试进度,刚开始是怀疑有同事人为的对数据进行修改,几经排查发现是由于在使用idea编译打包过程中,会自动执行代码工程中单元测试方法,单元测试方法中有对数据库表记录的增删改查操作。部分精心准备的测试数据,在每次执行maven package的时候被篡改。解决办法:在打包时关闭单元测试,关闭方法点开ideamaven面板,点击一个闪电标记即可,如下图:


本周技术问题总结--2017.09.01
            
    
    博客分类: 每周总结 log4jslf4jjvm调优 
 

 

 

二、log4jslf4j包冲突

 

冲突包为log4j-over-slf4j.jarslf4j-log4j12.jar,现象为tomcat启动失败,错误日志内容为:

java.lang.*Error

Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path

 

从日常上看是log4j-over-slf4j.jarslf4j-log4j12.jar冲突了,冲突原因分析:

首先看下slf4j-log4j12.jar(转接到log4j日志框架,正向过程,官网:官网https://www.slf4j.org/manual.html#swapping

slf4j不是日志框架,而是日志打印规范,log4j是日志框架负责具体的日志打印(类似流行的还有logback,据说比log4j的性能更好)。他们的关于有点类似于jvm规范和Hotspot的关系,一个是规范,一个是具体的实现。

 

这里slf4j是规范,封装了各种日志打印规范,比如可以使用占位符打印日志: logger.error("{}登陆成功,登陆时间{}",userid“2017-09-01”)。最终具体的日志打印操作交给log4j处理。

这时就需要引入slf4j-log4j12.jar,依赖关系为:slf4j-api.jaràslf4j-log4j12.jaràlog4j.jar

如果有一天你想切换到性能更好的logback日志框架,只需把slf4j-log4j12.jar包替换为logback即可。

 

再来看下log4j-over-slf4j.jarlog4j调回slf4j,逆向过程,官网:https://www.slf4j.org/legacy.html

使用log4j-over-slf4j取代log4j,这样log4j接口输出的日志就会通过log4j-over-slf4j路由到SLF4J上,这样即使系统(包含使用的第三方jar库,比如dubbo)都可以将日志最终路由到SLF4J上,进而集中输出。这个依赖关系为:log4j-over-slf4j.jar à slf4j-api.jar,可以看到这个依赖关系刚好与上述相反,导致出现无限相互递归依赖,最终导致溢出。

 

参考:

http://blog.csdn.net/kxcfzyk/article/details/38613861?utm_source=tuicool

http://blog.csdn.net/john1337/article/details/76152906

 

 

三、user.name配置与系统环境变量重名失效

 

好心网友sxp2558SkySchedulehttp://moon-walker.iteye.com/blog/2386504)过程中发现一个bug:笔者在配置netty连接使用的用户名时,在properties文件中配置的key” user.name”,代码中配置的值为“moon” 但实际使用的时候通过spring上下文Environment获取到的值为当前服务器的主机名,导致SkySchedule的客户端无法与服务端连接成功。

 

根本原因为:” user.name”为默认系统常量,配置在properties中的值会被覆盖,导致读取到的是主机名,而不是properties文件中配置的用户名。

 

目前已经改为“sky.user.name”,代码已提交到github。再次感谢sxp2558

 

四、jvm内存报警

 

本周项目所属系统出现几次jvm内存报警,内存使用率超过80%

首先分析系统采用垃圾回收算法:年轻代采用的ParNew收集器,年老代采用的Parallel Old收集器,都是采用的并行收集器,jdk版本是1.8

 

再看下GC情况,没有触发full gc,只有少量young GC,系统访问量也不高。初步分析是每次年轻代GC存活下来的对象较多,堆积到年老代的对象日益增加,同时有没有触发full GC导致。

 

解决办法:

1、可以写个定时任务,每晚凌晨2点,业务闲时调用system.gc() 触发full gc

2、当内存使用到达一定的百分比时,自动触发full GC

 

第一种办法,需要重新上线,暂时没有采纳。

第二种办法,可以把年老代改用CMS收集器,CMS收集器有个CMSInitiatingOccupancyFraction参数,可以控制当年老代内存使用到达一定的比值,自动触发full GCParallel收集器没有找到类似的参数。同事最终把参数改为:

-XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=65

具体含义为:采用cms垃圾收集器;开启碎片整理;5full GC后进行一次碎片整理;年老代内存超过65%,自动进行full GC

 

 

由于cms垃圾收集器都cpu要求很敏感,修改jvm参数后,再进一步观察下 根据情况决定是否切回Parallel垃圾收集器。

  • 本周技术问题总结--2017.09.01
            
    
    博客分类: 每周总结 log4jslf4jjvm调优 
  • 大小: 14.3 KB