大家在看文章之前先幫我看個問題(已解決 詳細):
reload幾次之后tomcat就掛了,我說的掛了,是指java進程占了CPU的幾乎全部,整個電腦像死機一樣,狂慢。
一年半前的一個項目也是使用的struts,hibernate,spring,沒有這個現象,記不起是從什么時候開始的了。
以前也就忍了,但現在給客戶做了一個tomcat的管理工具(因為需要和項目中的一些內容結合在一起所以單獨做的),發布幾次tomcat就掛了,導致這個工具意義變的不大了。
對tomcat進行管理
??? 研究了一下probe,了解到了一些基本的知識,現在準備,自己做tomcat的管理了。我是說這個項目中需要的對tomcat的那些管理功能,并不是完整的管理。
??? tomcat里對容器資源是層層管理的,Servlet由Wrapper管理,Wrapper之上是Context(對應一個application, server.xml里的一個Context配置),再上是Host,再上是Engine。到了Host使用findChildren可以獲取所有的 Context。Wrapper,Context,Host,Engine,都是繼承Container的接口,tomcat里的實現類 (StandardXXX),又都是繼承抽象類ContainerBase的,而ContainerBase又實現了Container, Lifecycle, Pipeline, MBeanRegistration, Serializable這些接口,所以當你獲取到這些容器類的實例后可以根據你的需要將之轉換為上述這些類型,進而獲取其他的相關信息和執行特定的操作。具體情況可以參考
http://zhangjunhd.blog.51cto.com/113473/19865
http://tomcat.apache.org/tomcat-5.5-doc/architecture/index.html
http://tomcat.apache.org/tomcat-5.5-doc/catalina/docs/api/index.html
??? 要獲取這些容器實例,一個方法是獲取到Wrapper,然后進而獲取其上級容器。就現在我了解到的情況,將一個servlet實現 org.apache.catalina.ContainerServlet接口就可以獲取到一個 org.apache.catalina.Wrapper對象了,其他的方法我還不知道,我想應該存在一些更直接的獲取Host對象之類的方法,抽時間看看tomcat本身的管理功能的代碼。
??? 為了利用起原來的框架,并且納入對tomcat信息的管理,我現在分別做了兩個處理:
- 給Action注入Wrapper對象。
我現在的策略是寫一個TomcatManagerServlet實現ContainerServlet,獲取Wrapper,然后將之保存到request的attribute里,然后forward到當前管理系統框架下的相應的action里。
具體的方法是:在web.xml里配置這個servelt,并且指明所有的*.d會到這個servlet里來,然后到了這個servlet里后保存 Wrapper,然后forward到request.getRequestURI()+"o"。這樣原來的頁面里只要把鏈接地址從xxx.do改為 xxx.d就可以了。本來以為這個方法滿好的,不過如果不是.do的請求就玩不起來了。現在覺著應該是在原有的鏈接之前加上一個額外路徑更合適些,比如原來是/xxx/yyy.do,現在寫成/tomcatManager/xxx/yyy.do,然后在TomcatManagerServlet里去除路徑中的/tomcatManager再進行forward。這樣下面的jsonrpc的servlet也不用修改了,但jsonrpc的前臺要修改。終極一點是寫一個servlet處理所有的請求,如果路徑中含有/tomcatManager或者參數中含有tomcatManager,就給request里添加Wrapper對象。
- 給jsonrpc調用的對象注入Wrapper。
上面這個方法其實我還沒真正用,因為實際開發的時候我是使用ajax來操作的。方法類似,首先還是要把jsonrpc的servlet實現ContainerServlet接口,獲取Wrapper,存入request的 attribute。如果被調用的方法定義了request參數,那么就可以從中獲取Wrapper對象了。但這樣比較繁瑣,我寫了一個 WebServerManager(今后會抽象為接口),定義了public void setWrapper(Wrapper wrapper)方法,然后寫了一個jsonrpc的callback,并注冊給jsonrpc,在callback里將Wrapper注入給 WebServerManager。這樣WebServerManager就更通用和簡潔一些了。
?
上面只是說了tomcat的Container的基本內容,以及如何將獲取Wrapper進而獲取整個Container的方法。另外和我們自己的基礎代碼比較相關,所以你若要具體了解如何使用這些 Container對tomcat進行操作可以去查看probe的 org.jstripe.tomcat.probe.Tomcat55ContainerAdaptor及其父類和 org.jstripe.tomcat.probe.tools.ApplicationUtils,我覺著這兩個類比較基礎。理解了這兩個類,就可以方便的進一步了解了。