前提:
公司項(xiàng)目用的是nginx+tomcat+java,線上環(huán)境和線下環(huán)境版本配置都是一樣,采用的是jenkins自動化部署。
問題:
前段時(shí)間突然發(fā)現(xiàn)瀏覽器訪問一個頁面,后端日志會出現(xiàn)重復(fù)的兩條日志記錄一模一樣,請求時(shí)間都是一樣的,經(jīng)過測試發(fā)現(xiàn)所有的請求都會有兩條重復(fù)的日志記錄。如下圖:
排查:
1、一開始認(rèn)為是前端重復(fù)請求了,查看nginx訪問日志,發(fā)現(xiàn)刷新一次頁面的確nginx會出現(xiàn)兩條請求記錄,一次是OPTIONS請求,一次是GET請求,但是監(jiān)控tomcat日志,發(fā)現(xiàn)刷新一次頁面有4次請求,兩次完全相同(包括時(shí)間)的OPTIONS和兩次完全相同的GET請求。
2、排除前端頁面問題以后,開始懷疑是nginx重復(fù)請求導(dǎo)致,于是直接通過IP+tomcat端口訪問,發(fā)現(xiàn)還是會有完全一模一樣的兩條日志。然后通過IP+端口測試其他幾個后端api,都會出現(xiàn)一樣的問題。
3、排查nginx和前端以后,把問題鎖定在了tomcat環(huán)境上面,于是開始一步一步排查:
a、對比了線上和線下的tomcat版本、java版本以及diff對比了線上和線下的實(shí)例配置文件,都是完全一樣的。
b、百度搜索以后,有網(wǎng)友說重復(fù)請求問題是因?yàn)樵趖omcat的默認(rèn)的server.xml里面,錯誤的配置了Host或者Context標(biāo)簽導(dǎo)致兩個對象同時(shí)持有日志文件,導(dǎo)致重復(fù)加載。
①如果新增了Host,那Host/appBase的值是不能和其他Host/appBase的值一樣的。比如appBase都是webapps,那么兩個Host會導(dǎo)致webapps下面的工程被加載兩遍。
②如果配置了Context標(biāo)簽?zāi)敲淳鸵欢ㄒ渲胣ame屬性值為:工程名(/web-sys),或者配置path值為工程名(/web-sys),否則就會引起重復(fù)加載工程的問題。
③<Alias>標(biāo)簽,允許我們把多個域名配置在一個Host下面,例如:xxx.com、xxx.cn、xxx.com.cn,都可以配置在一個Host下面
需要配置成下面這樣:
<Host name="www.xxx.com" appBase="mywebapps" autoDeploy="true" unpackWARs="true">
<Alias>www.xxx.cn</Alias>
<Alias>www.xxx.com.cn</Alias>
<Context docBase="web-sys" path="" name="/web-sys"/>
</Host>
我對比了我的server.xml文件,于是添加了name屬性,然后刪除了默認(rèn)的ROOT目錄,進(jìn)行了一番測試,結(jié)果還是會出現(xiàn)顯示兩條重復(fù)日志的問題。
4、經(jīng)過上面的排查以后,開始有點(diǎn)迷茫,于是把線上的實(shí)例war包直接拷貝到了本地環(huán)境,然后修改了數(shù)據(jù)庫信息,經(jīng)測試還是會有同樣的問題。此時(shí)瞬間又找到了方向,應(yīng)該是war包封裝過程中的問題。
5、于是去查看jenkins 線上和線下構(gòu)建過程,發(fā)現(xiàn)配置文件有個redis參數(shù)不一樣、log4j2.xml日志級別不一樣,swagger開啟狀態(tài)不一樣,然后馬上把新建一個實(shí)例,把jenkins構(gòu)建過程改成和本地測試環(huán)境一樣,重新構(gòu)建部署到生產(chǎn)環(huán)境,訪問測試終于正常了。
6、這次終于找到了原因,于是依次對上面幾個不同的參數(shù)一個一個修改發(fā)布測試,最后發(fā)現(xiàn)是因?yàn)閘og4j2.xml里面少了additivity="false"這個屬性導(dǎo)致。(一旦一個日志輸出到一個Logger,這個Logger的additivity設(shè)置為false,那么這個日志不會再繼續(xù)向父Logger進(jìn)行傳遞,忽略其他Logger的additivity的設(shè)置。)
7、最后再去排查為何會少一個屬性,才發(fā)現(xiàn)是jenkins構(gòu)建過程中,使用sed命令替換時(shí),使用了.*通配符去替換日志等級level="DEBUG",導(dǎo)致把a(bǔ)dditivity="false"替換為了空。
<Logger name="cn.amd5.community" level="DEBUG" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="DailyLogFile"/>
</Logger>
加上additivity="false"以后,重啟實(shí)例,測試正常,如下圖: