tomcat6 使用comet衍生出的兩個額外問題

開發了一個輪詢推送功能,網上也有不少文章講這個就不說怎麼作的了。如今發現兩個問題:html

一:就是登陸進主頁面後,因爲瀏覽器在不停輪詢,致使後端認爲前端一直在操做,而正常設定的session超時就跳轉到登陸頁面的功能就失效了。由於服務器認爲這個session一直活躍着的。前端

本覺得tomcat會有配置,特定的url不算入session的accessTime,找了好久沒有這個功能。那就想有沒有辦法控制瀏覽器發送請求的時候不帶上JSSESSIONID的cookie,也沒辦法實現。因此只有用本身寫代碼的形式來控制了。web

總的思路有兩種,一種是後端控制,另外一種是前端控制。apache

  後端控制的思路就是用過濾器過濾全部請求,把輪詢的請求排除,本身來計算session超時的時間,到了就調用session銷燬的方法。特別說明一點映射到實現tomcat6的CometProcessor的servlet的url不會通過Filter,這樣自動就排除了(一開始不曉得,我還去在struts.xml的配置裏把這個url設爲excludePattern,其實徹底不必,由於都不會通過struts2的過濾器)。後端

  前端控制的思路是用一些js框架監控前端的事件,若是長時間沒有操做,就發送logout請求到服務器。瀏覽器

---------------------------------------------------------------------------------------------------------------------------tomcat

tomcat6一個特殊屬性:服務器

 

org.apache.catalina. STRICT_SERVLET_COMPLIANCE

If this is true the following actions will occur:cookie

  • any wrapped request or response object passed to an application dispatcher will be checked to ensure that it has wrapped the original request or response. (SRV.8.2 / SRV.14.2.5.1)
  • a call to Response.getWriter() if no character encoding has been specified will result in subsequent calls to Response.getCharacterEncoding() returning ISO-8859-1 and the Content-Type response header will include a charset=ISO-8859-1 component. (SRV.15.2.22.1)
  • every request that is associated with a session will cause the session's last accessed time to be updated regardless of whether or not the request explicitly accesses the session. (SRV.7.6)
  • cookies will be parsed strictly, by default v0 cookies will not work with any invalid characters. 
    If set to false, any v0 cookie with invalid character will be switched to a v1 cookie and the value will be quoted.
  • the path in ServletContext.getResource / getResourceAsStream calls must start with a "/".
    If set to false, code like getResource("myfolder/myresource.txt") will work.

 

If this is true the default value will be changed for:session

  • org.apache.catalina.connector.Request. ALLOW_EMPTY_QUERY_STRING property
  • org.apache.tomcat.util.http.ServerCookie. PRESERVE_COOKIE_HEADER property
  • The webXmlValidation attribute of any Context element.
  • The webXmlNamespaceAware attribute of any Context element.
  • The tldValidation attribute of any Context element.

 

If not specified, the default value of false will be used.

這個屬性默認值是false。

也就是說咱們不設這個值的話,tomcat6去更新session的最後使用時間會在getsession方法被調用的時候纔去執行。也就是說若是咱們代碼裏不顯示的去獲取session的話,即便帶着jssessionId這個cookie的請求進來,tomcat也不會去更新session訪問時間。因此就很好辦了,只要咱們輪詢url訪問的servlet裏不顯示調用session就OK啦。

反編譯tomcat源碼出來看了下,若是在tomcat\conf目錄下的catalina.properties裏把org.apache.catalina. STRICT_SERVLET_COMPLIANCE爲true了。那麼容器在org.apache.catalina.core.StandarHostValue的invoke方法會執行request.getSession(false);這樣時間就被更新了。

 

 

二:CometProcessor的線程局部變量問題。

  發現一個請求的生命週期裏 CometEvent是BEGIN和ERROR的時候CurrentThread並非同一個(其餘兩種事件類型的狀況沒試),而Request是同一個(不是同一個豈不亂套了)。推測tomcat在使用NIO的時候不一樣的CometEvent並無必定要同一個Thread來執行,而是從線程池裏取一個來執行,固然上下文(主要是Request,Respose)是要保持着的,每次執行的時候要傳進來。這也是能理解的,畢竟NIO就是爲了大併發處理嘛,執行Begin的那個線程把Begin的邏輯執行完了就該放入線程池裏供其餘請求使用,若是必定要Error的時候再用這個線程來執行,那這段時間這個線程就不能複用了,也就失去了NIO的意義。

  項目裏用了一個ThreadLoacl,都在一個全局的Filter裏進行設置。開發完輪詢功能正常,後來發現輪詢的請求根本沒進入那個設置ThreadLoacl的Filter,(前面說了CometProcessor的servlet不會通過普通Filter),那怎麼還在正常使用呢,ThreadLoacl還有值。緣由是其餘請求在線程上設置了這個值,線程完了進入線程池並無執行清除的操做,因此如今從線程池取出來ThreadLoacl也是有值的。(線程對象就是ThreadLoaclMap的一個Key而已)。因此爲了正確,CometProcessor裏也要進行ThreadLocal的初始化。

相關文章
相關標籤/搜索