1. 程式人生 > >一次由Tomcat重新載入引發的血案

一次由Tomcat重新載入引發的血案

引言: Tomcat是目前開發中使用非常廣泛的Web伺服器,其提供了很多優秀和簡便易用的功能。我們這裡的血案就是由於在部署過程中,不慎而引發的....

1. 問題的出現

    在我們的系統後臺每日定義會觸發一些任務操作,進行一些資料的處理和更新,從上線到現在已經正常運行了將近3個多月了。忽然某一天,發現其資料不對,大量的資料都是被執行了2次某個定時任務A造成的。 查詢日誌,的確是執行了2次。但是之前為什麼是正常的呢?詭異詭異....

    環境: Tomcat 6.0.x

2.  血案的發生

   由於在生產系統中,資料出現了問題,這個是一個非常嚴重的事情。於是首先把這個定時任務A先停掉,清理資料。由於資料量比較大,所以就有了焦頭爛額的幾天修正系統資料的過程。

3.  問題分析

    3.1  任務A本身有問題嗎?

          之前都是正常執行的, 只在最近幾天才發生問題。而且基於日誌分析,其資料操作是正確的,問題是操作了2遍。

    3.2  任務A實現分析

          首先懷疑其實現的程式碼上是否有問題? 經過分析其是基於Quartz來實現定時任務的,Quartz是老牌的定時框架,不會出現問題。 是否是我們自己使用的方式問題,並只在特定情況下才會出現問題呢? 經過程式碼的排查分析,沒有問題。

     3.3  程式碼變更記錄分析

         是否是某個同事無意之前做的什麼修改造成的呢? 經過針對程式碼變更記錄和上線記錄的分析,排除這個可能。

4.  系統日誌分析

     在排除了這個任務A自身問題之後,將目光轉移到了環境本身。  部署環境是Tomcat6.  下載了Tomcat日誌檔案進行分析,逐漸找到了某些蛛絲馬跡,從而剝絲抽繭般的發現了問題的原因。

     在系統日誌中,發現了若干在應用部署過程中的錯誤資訊,這個引起了我的懷疑。是否是由於在部署中的錯誤造成的呢?

     經過排查,確定是部署不慎造成的,而且是由於Tomcat本身的Reloadable特性造成的問題。

 5.  問題場景的還原

     1.  某位同事由於在修改某個問題,只修改了某幾個Class檔案,故其將編譯後的class檔案在伺服器上直接進行了替換。

      2.   由於Tomcat本身設定了Reloadable的屬性,故Tomcat在檢測到class檔案發生變化之後,對WebApp的應用進行了重新載入:先解除安裝,再重新載入。

      3.   在解除安裝的過程中,程式出錯,解除安裝失敗,原來的應用沒有解除安裝成功,保留在Tomcat的快取之中。

     

     4.   雖然解除安裝失敗,Tomcat繼續載入新的WebApp應用。這裡請注意: 新載入的WebApp應用在專案名稱之後加了一個2,比如原來的專案名稱是AAA, 新的專案名稱就是AAA2。 重新定義了一個專案名稱哦,我當時就知道,這裡就是問題所在。

     

  此時,二次載入的Web應用,也由於某些原因失敗了。

    

5.  運維的同事,注意到了這些錯誤資訊,由於重新啟動了Tomcat,這次Tomcat正常啟動了

     第一個Web應用正常啟動了

     

    第二個Web應用也正常啟動了,參看日誌。

    

6.  於是在我們的Tomcat中就出現了兩個一模一樣的Web應用,換句話說,就是出現了兩個一模一樣的定時任務。 這個就是為什麼定時任務會被執行2次的原因。

7. 解決以及應對

      7.1 不允許動態的在生產系統中,替換class檔案

     7.2  在系統部署和上線過程中,需要進行日誌分析,日誌可以告訴我們一切的技術細節和內容。

     7.3  將Tomcat的Reloadable設定置為false

          <Context path="/helloApp" docBase="helloApp" debug="0" reloadable="false"/>  

8.  reloadable引數說明

     Context>代表了執行在<Host>上的單個Web應用,一個<Host>可以有多個<Context>元素,每個Web應用必須有唯一的URL路徑,這個URL路徑在<Context>中的屬性path中設定。      

    <Context path="/helloApp" docBase="helloApp" debug="0" reloadable="true"/>  
<Context>元素的屬性:
path:指定訪問該Web應用的URL入口。
docBase:指定Web應用的檔案路徑,可以給定絕對路徑,也可以給定相對於<Host>的appBase屬性的相對路徑,如果Web應用採用開放目錄結構,則指定Web應用的根目錄,如果Web應用是個war檔案,則指定war檔案的路徑。
reloadable:如果這個屬性設為true,tomcat伺服器在執行狀態下會監視在WEB-INF/classes和WEB-INF/lib目錄下class檔案的改動,如果監測到有class檔案被更新的,伺服器會自動重新載入Web應用。
在開發階段將reloadable屬性設為true,有助於除錯servlet和其它的class檔案,但這樣用加重伺服器執行負荷,建議在Web應用的發存階段將reloadable設為false。

9.  總結

     由於一個微小的變化引發的問題,在這之前一直正常。由於動態替代class,引發自動部署;部署失敗,導致出現了2個相同的部署包。再次重啟,然後2個快取包都正常啟動。 其本質原因是Tomcat在解除安裝應用的過程中,如果出現異常,則無法繼續刪除快取;在重新載入的時候,無法清空已有的快取,這個才是問題的根源。

    我們姑且把這個問題,作為Tomcat的一個bug吧,只在特定情況下才會出現的問題。

相關推薦

Tomcat重新載入引發血案

引言: Tomcat是目前開發中使用非常廣泛的Web伺服器,其提供了很多優秀和簡便易用的功能。我們這裡的血案就是由於在部署過程中,不慎而引發的.... 1. 問題的出現     在我們的系統後臺每日定義會觸發一些任務操作,進行一些資料的處理和更新,從上線到現在已經正常運行了

tcp_tw_recycle參數引發血案

not 登陸 解決辦法 pin 有客 cau 只有一個 mps 導致 一,故障描述: 從昨天開始,在值班群中陸續值班人員反映系統後臺存在卡頓問題,如下圖:而且在卡頓的同時登陸服務器也會卡好久。此現象只在一臺服務器有出現。 二,故障分析: 1,登陸服務器查看資源使用top,v

echo '' > 引發的問題

本篇文章大概閱讀時間2分鐘 最近公司生產環境伺服器經常記憶體報警,而且多發生在凌晨,見下圖。 由於一直報警,因此寫了一個記憶

python的print函式引發血案

我最近專案是基於自研的webserver框架實現的,支援C++、Java、Python等語言混合開發,上線一年多都沒有發現重大問

內聯元素錯位引發對line-height的思考

作者:李一睿 line-height 對於一個前端小可愛來說,應該是一個會經常碰面的老朋友了。可是有一天,我突然發現自己好像對他沒那麼瞭解,他也沒有外表看起來的那麼簡單。 事情的經過是這樣的…… 在偶然一次工作中,我寫了這樣的模板: <div> <span clas

伺服器Tomcat優化經歷

公司需要一臺測試伺服器來做測試用,所以花了點時間把服務全部部署好,在部署好war包之後,發現Tomcat訪問超級慢。 1、進入Tomcat的bin目錄下,執行 ./catalina.sh run命令,在前臺列印執行資訊,首先看其有沒有報錯。好,沒有報錯,進行下一步。 1)修改你的jdk目錄下/

記錄屁股決定研發的狗血經歷

大將無能,累死三軍。一個專案的成敗,是整個團隊努力的結果。今天總結的這些經驗教訓,如果對後來人有哪怕一丁點的經驗教訓,那也值了。 2017年的春天,我們團隊接到一個任務,需要開發一套智慧家居產品,產品的開發週期初定為三個月。產品的架構其實不復雜,都是一些現成的技術,應該很快可以拿下。 事實證明,碼農的

jdk版本導致的錯誤

異常表現 專案本地開發環境啟動正常, 部署到生產環境啟動卡死. 解決步驟 首先當然是找到啟動日誌. 由於專案在windows Server 2012上執行, 註冊為windows服務. 所以不會有控制

線上問題排查所引發的思考

前言 之前或多或少分享過一些記憶體模型、物件建立之類的內容,其實大部分人看完都是懵懵懂懂,也不知道這些的實際意義。 直到有一天你會碰到線上奇奇怪怪的問題,如: 執行緒執行一個任務遲遲沒有返回,應用假死。 介面響應緩慢,甚至請求超時。 CPU 高負載執行。 這類問題並不像一個空指標、陣列

使用innobackupex重新搭建主從複製報錯解決方法及注意事項

【環境介紹】   系統環境:CentOS release 6.4 (Final) + Server version: 5.7.18-log MySQL Community Server (GPL) + innobackupex version 2.4.12 Linux (x86_64)

記錄奇葩tomcat啟動異常!!!

我的電腦同時使用兩個jdk版本,預設1.7,eclipse使用的是1.8,,由於專案啟動時有載入類需要jdk1.8的包,1.7不支援。所以導致專案在eclipse直接能夠跑,而在外面的tomcat跑是就出現startup failed due to previous erro

記錄釋出tomcat專案到測試環境的問題

公司的官網專案,還沒使用到前後端分離,根據需求本地測試完以後,釋出到測試環境時出現問題。 首先是打包,專案可以正常啟動,但是通過maven打包的時候報錯 原因是這個專案的pom中呼叫到了公司內網的依賴,但是idea中的maven使用的是阿里雲的映象,所以無法打包成功。

Tomcat有關的Too many open files錯誤

前言 最近在公司開發推送系統相關的專案,需要在單臺Linux伺服器上支援幾十萬到上百萬的連線,為此,修改了作業系統的檔案描述符上限。 相關修改操作可參考: 修改並重啟後使用ulimit -a檢視發現open-file變大。之後,使用netty簡單構建一個服務端demo

解決tomcat自動關閉的bug

最近一個運行了4年的javaee web專案,經常接到客戶反饋系統無法開啟。登入伺服器檢視服務,發現是tomcat自動關閉了。基本是3到4天發生一次。 運維人員開始以為是其他服務殺死了tomcat服務,沒放在心上,解決方法就是直接重啟tomcat。 最終捅了簍子,運維人員被客戶投訴,扣了一個月的績效。 解決這

selinux引起的使用cat檢視檔案報錯Permission denied的問題排查

事件起因:如下 1、在伺服器上root使用者,會定期生成一個檔案,到/tmp目錄,如:qq_5201351.txt,給other加上了r讀取 2、zabbix端會週期性取這臺伺服器/tmp/qq_5201351.txt檔案內容的(只能通過agent方式,system.run[cat /tmp/qq_52013

@Controller引發血案

request mapping handle 今天收到了一份spring mvc的工程,看裏面沒有加controller,想著加個默認的Controller明眼人是不是一眼就看到問題所在了?如果沒有發現問題的,請跟著我的思路一起混亂下去啟動工程沒報錯,說明其他的結構沒問題打開瀏覽器,輸入http:

活動引發血案

機器學習 相關 target dubbo 一起 底層 是否 等待 取余 本文來自網易雲社區作者: 方金德 “咚咚”,接連收到好幾個報警短信,顯示線上集群的幾個tomcat應用的接連端口異常。不好,線上可能出狀況了,訪問網站,果然已經顯示為維護中了。趕緊登陸到服務器,但服務器

【小家Java】Java執行緒池誤用(newFixedThreadPool)引發的線上血案和總結

相關閱讀 【小家java】java5新特性(簡述十大新特性) 重要一躍 【小家java】java6新特性(簡述十大新特性) 雞肋升級 【小家java】java7新特性(簡述八大新特性) 不溫不火 【小家java】java8新特性(簡述十大新特性) 飽受讚譽 【小家java】java9

Redis的hGetAll函式所引發服務宕機事件

昨晚通宵生產壓測,終於算是將生產服務宕機的原因定位到了,心累。這篇部落格,算作一個覆盤和記錄吧。。。   先來看看Redis的快取淘汰演算法思維導圖: 說明:當實際佔用的記憶體超過Redis配置的maxmemory時,Redis就會根據使用者選擇淘汰策略清除被選中的key。  

裝mysql服務引發血案

上午閒玩dos命令,因為dos命令無法啟動mysql服務,於是百度查詢原因,然後從裝了服務。從這裡開始一場沒有硝煙血案就開始了。 從裝mysql服務之後,按原來的方式(原來的使用者名稱密碼)連線資料庫,可是不管怎樣都連線不上 這是什麼原因呢?我想了想,試試不填寫密碼看能不