Tomcat他山之石.能夠攻玉(一)Server組件

 

   Server組件

       Server組件做用:

  • 採用觀察者模式,又叫源-收聽者的設計模式,提供了能夠動態添加、刪除的監聽器,做用是在Server組件的不一樣生命週期中完成不一樣的功能、邏輯;
  • Tomcat容器的全局命名資源實現
  • 提供關閉Tomcat方式(接收端口收到的SHUTDOWN命令).

 

  Server組件監聽器

    Server組件監聽器默認是六個

  1. NamingContextListener
  2. VersionLoggerListener
  3. AprLifecycleListener
  4. JreMemoryLeakPreventionListener
  5. GlobalResourcesLifecycleListener
  6. ThreadLocalLeakPreventionListener

 

    Server組件監聽器說明

      監聽器的做用就是在Tomcat各個組件如Server、Service、Context的某個生命階段完成某些邏輯處理而出現,  使用方式 實現LifecycleListener接口,加入到組件的監聽器集合中addLifecycleListern,邏輯處理寫在LifecycleListener實現類的lifecycleEvent中。html

1.  NamingContextListener

   NamingContextListener監聽Tomcat啓動以前、結束以前進行邏輯處理,在Tomcat啓動以前建立、綁定命名資源,在Tomcat結束以前解綁命名資源,這個主要涉及到Ejb、JNDI等,全局命名資源存放在Server的globalNamingResources中,全局命名資源的意義:好比JNDI,在weblogic中資源名爲jdbc/nbrSz,在Tomcat中就須要使用全局命名資源來訪問,全局命名資源建立、綁定、解綁等工做就是由NamingContextListener來完成.java

 

    2.VersionLoggerListener

    針對Tomcat初始化以前進行必要的日誌操做,主要打印版本信息、機器環境信息;web

image

 

   3.AprLifecycleListener

    Tomcat可使用本地APR進行調優,調用本地庫提升對靜態文件處理能力。 AprLifecycleListener主要針對Tomcat初始化以前、銷燬以後進行操做,初始化以前嘗試初始化APR庫,成功則使用APR接受處理客戶端請求;Tomcat銷燬以後,該監聽器會作APR的清理工做.數據庫

 

4.JreMemoryLeakPreventionListener

    該監聽器主要用來解決內存泄露和鎖文件,在Tomcat初始化以前使用系統類加載器加載一些類,而且設置緩存屬性來達到避免內存泄露和鎖文件的目的。設計模式

    內存泄露,垃圾回收機制,若是一個想要回收對象被另一個生命週期很長的對象一直引用着,GC是沒法回收這個「垃圾對象」。還一種內存泄漏由於類加載器致使的,JRE庫中某些類運行時以單例存在,從程序啓動到關閉。JRE庫這些類使用上下文類加載器加載,保留了上下文類加載器的引用,就致使了被引用的類加載器沒法回收。  Tomcat部署多個Web應用使用不一樣的上下文類加載器,舊的上下文類加載器沒法被回收,就致使了內存泄露。緩存

   好比DriverManager.getDrivers();  在某個Web應用中咱們調用這句話,數據庫驅動以單例形式存在,持有這個web應用的上下文類加載器,後面部署另外的Web應用,每一個加載JRE中單例類的app

類加載器,後面都會變成沒法被回收的對象,致使內存泄露。socket

   除了上面的JRE單例致使類加載器沒法被回收之外,還一種狀況就是,JRE中某些類,線程加載它的時候會建立新的線程而且無線循環,新的線程上下文類加載器會繼承父線程的類加載器,新線程就包含上下文類加載器,致使父類上下文類加載器沒法被回收,內存泄露問題出現,好比某上下文類加載器加載Disposer類。ui

 

   JreMemoryLeakPreventionListener就是防止JRE內存泄露問題,解決方案就是先將當前線程類加載器保存起來,用系統類加載器去加載這些會致使JRE內存泄露的類,  這樣作之後好比Web應用用到這些類,雙親委派模型在系統類加載器中找到了就不會再加載一遍防止內存泄露,加載完成這些隱患的類後再講原來的類加載器還原。  其餘可能致使內存泄漏的類:ImageIO.getCacheDirectory()、 java.awt.Toolkit.getDefaultToolkit()、sun.misc.GC、甚至j解析xml的DocumentBuilderFactory,這些類在JreMemoryLeakPreventionListener都有出現。spa

image

 

  鎖文件情景主要是在Windows下使用URLConnection讀取本地jar包內資源時,會將jar包內容緩存起來,當從新部署jar包會失效,仍是讀取的舊的資源。

JreMemoryLeakPreventionListener解決方案Tomcat初始化以前實例化URLConnection且禁用默認緩存便可。

image

 

      5.GlobalResourcesLifecycleListener

      GlobalResourcesLifecycleListener監聽Tomcat容器的啓動、銷燬,Tomcat啓動時GlobalResourcesLifecycleListener實例化JNDI資源的MBean,Tomcat中止時銷燬MBean.

 

      6.ThreadLocalLeakPreventionListener

     ThreadLocalLeakPreventionListener監聽Tomcat容器啓動後、中止前、中止後,目的是爲了防止ThreadLocal對象帶來的內存泄漏問題。

ThreadLocal帶來的內存泄露問題,Tomcat內部接收請求都是經過線程池的方式處理,線程池中線程生命週期通常都長,好比某個Web應用A,常用ThreadLocal保存一些信息A,A又是由Web應用的WebappClassLoader加載的, 假設部署新的Web應用,實例化了新的WebappClassLoader,線程池中線程一直在運行着或等待着,可是舊的WebappClassLoader因爲A保留着引用沒法被回收,這樣就致使了內存泄露。

     解決方案就是當新的Web應用部署時,將全部的線程池內全部線程銷燬而且從新建立新的線程。

 

    程序方式結束Tomcat

       除了可執行腳本bat/sh方式結束Tomcat,Tomcat還提供咱們一種程序的方式結束Tomcat:

            當程序部署在Tomcat中,咱們只須要可以執行下面代碼,就可以結束Tomcat的一輩子:

public class ShutDownCli {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("localhost",8005);
        OutputStream os = socket.getOutputStream();
        os.write("SHUTDOWN".getBytes());
        socket.close();
    }
}

      原理就是 Tomcat啓動後主線程和守護線程兩種,主線程一直在監聽server.xml中<Server>的port,也就是8005端口,而守護線程纔是用來接收請求並處理的。主線程8005端口收到SHUTDOWN命令,主線程執行Tomcat關閉並退出,主線程結束,Tomcat就結束了。

相關文章
相關標籤/搜索