天天看點

Tomcat-connector的微調(3): processorCache與socket.processorCache

這個cache是一個<code>concurrentlinkedqueue</code>,預設最多可緩存500個對象(見<code>socketproperties</code>)。可以通過<code>socket.processorcache</code>來設定這個緩存的大小,注意這個參數是nio特有的。

接下來在<code>socketprocessor</code>執行過程中,真正的業務邏輯是通過一個<code>org.apache.coyote.processor</code>的接口來封裝的,預設這個<code>processor</code>的實作是<code>org.apache.coyote.http11.http11processor</code>。我們看一下<code>socketprocessor.process(...)</code>方法的大緻邏輯:

上面的方法是在<code>abstractprotocol</code>模闆類裡,是以bio/apr/nio都走這段邏輯,這裡使用了一個回收隊列來緩存<code>processor</code>,這個回收隊列是<code>concurrentlinkedqueue</code>的一個子類,隊列的長度可通過server.xml裡connector節點的<code>processorcache</code>屬性來設定,預設值是200,如果不做限制的話可以設定為-1,這樣cache的上限将是最大連接配接數<code>maxconnections</code>的大小。

在原有的一張ppt上加工了一下把這兩個緩存隊列所在位置标示了一下,圖有點亂,重點是兩個綠顔色的cache隊列:

Tomcat-connector的微調(3): processorCache與socket.processorCache

圖中位于上面的<code>socket.processorcache</code>隊列是nio獨有的,下面的<code>processorcache</code>是三種連接配接器都可以設定的。<code>processorcache</code>這個參數在并發量比較大的情況下也蠻重要的,如果設定的太小,可能引起瓶頸。我們模拟一下,看看這個瓶頸是怎麼回事。先修改server.xml裡的connector節點,把<code>processorcache</code>設定為0:

啟動tomcat後,使用ab模拟并發請求:

然後在ab的執行過程中立刻執行jstack觀察堆棧資訊,會發現一大半線程阻塞在<code>abstractconnectionhandler.register</code>或<code>abstractconnectionhandler.unregister</code>方法上:

<code>register</code>和<code>unregister</code>分别是在建立和回收processor的時候調用的;看一下<code>createprocessor</code>方法裡的大緻邏輯:

tomcat對jmx支援的非常好,運作時資訊也有很多可以通過jmx擷取,是以在每個新連接配接處理的時候,會在建立processor對象的時候注冊一把,然後在processor處理完回收的時候再反注冊一把;但這兩個方法的實作都是同步的,同步的鎖是一個全局的<code>connectionhandler</code>對象,造成了多個線程會在這裡串行。

絕大部分應用沒有特别高的通路量,通常并不需要調整<code>processorcache</code>參數,但對于網關或代理一類的應用(尤其是使用servlet3的情況)這個地方可以設定的大一些,比如調到1000或者-1。