星期一 四月 09, 2007

Sun Web Server 連線要求處理機制

時常被問到 Sun Java System Web Server (SJSWS) 有那些調校的空間。其實可調的參數很多,看你要調的是那一方面的功能。完整的調校除了 Web Server 本身設定之外、也必須包括底層作業系統的 TCP/IP 參數及檔案系統等非直接由 Web Server 控制但會被利用到的元件。建議先詳閱 Sun 官方調校文件,7.0版的文件為 Sun Java System Web Server 7.0 Performance Tuning, Sizing, and Scaling Guide,6.1 版的文件為 Sun Java System Web Server 6.1 SP4 Performance Tunning, sizing, and Scaling Guide,二個版本的調校原理是一樣的,能調的參數也差不多,最大的不同點是在於 7.0 大改管理架構,所以很多參數的名稱及設定位置在 7.0 及 6.1 是不一樣的。

由於參數很多,初閱調校文件時,你大概不太能了解每個參數彼此間的差異。我想最重要的是先了解 SJSWS 處理 HTTP 要求整個流程,才不會迷失在冗長的調校文件中。這是本篇重點,OK,進入主題吧 !

當遠端使用者以瀏覽器向你的 SJSWS 伺服器存取網頁時,在伺服器端發生下面的動作:

  1. TCP 連線 (Connection) 建立。
  2. 由接收緒 (Acceptor Thread) 接收來自遠端的 TCP 連線。
  3. 將接收的 TCP 連線排入佇列,等待工作緒 (Session Thread) 處理
  4. 工作緒處理 Http Request 。
  5. JVM 處理及回應 。

請不要忘記:雖然大多數人佈署 Java Web Application (WAR file) 在 SJSWS 上,但是這只是其中一種應用。SJSWS 並不是僅能處理 Servlet/JSP 要求。它是一個多功能的 HTTP Server ,也非常適合佈署 PHP、Perl、CGI 等程式。在以上的五個動作中,1-3 是處理 Connection 的動作,是由 Native Code 執行,4-5才是處理 HTTP 要求的動作,視所要求的程式為何,若為 Servlet/JSP 要求則由內部 in-process 的 JVM 處理,若為 PHP要求 則由 PHP 的 plugin 處理。習慣用 Apache 或是 Tomcat 的人常希望能以 Apache vs SJSWS 或 Tomcat vs SJSWS 來做評比,我認為以功能面來看,SJSWS = Apache + Tomcat。有與趣的請參考我之前的 Blog

好,細說各動作如下。

TCP 連線 (Connection) 建立

這一個階段和 SJSWS 沒有直接關連,而是使用者及伺服器二方 TCP/IP 層的互動。HTTP 依賴 TCP/IP,所以瀏覽器要送 HTTP request 前需先建立 TCP 連線。連線建立過程是利用所謂的 three way handshake (見 RFP 793 3.4 節) ,如下:

  1. 瀏覽器 --- [SYN] ---> Web伺服器
  2. 瀏覽器 <--- [SYN+ACK] --- Web伺服器
  3. 瀏覽器 --- [ACK] ---> Web伺服器

此時連線正在建立(也就是還沒有建立完成), 伺服器端 TCP 層需暫存住已發出 SYN+ACK 但還未收到 ACK 的連線要求。這一個暫存空間的大小由作業系統控制,以 Solaris 為例,是 tcp_conn_req_max_q0 參數(預設值為 1024)。

由接收緒 (Acceptor Threads) 接收來自遠端的 TCP 連線

當 handshake 完成後,二端 Socket Pair 確立,連線建立完成,SJSWS 隨時可接收(accept) 這一個連線。在被接收前,會被暫放在 listen backlog 中,SJSWS 的 listenQ 參數 (預設值為 128) 及 Solaris tcp_conn_req_max_q (預設值為 128) 都會對這個 backlog 的大小有影響,調整時二個參數要一起調。

官方文件建議將 tcp_conn_req_max_q0, tcp_conn_req_max_q, 以及 Web Server 的 listenQ 參數設定成同樣的值,如 8192 (視伺服器大小而異)。

接收連線是 Acceptor 的工作,SJSWS 的 Acceptor 是指一個或多個 Acceptor Thread(s),負責將 listen backlog 中的連線接收進來放到 Connection Queue 中。可調的參數為 Acceptor Thread 數目 (預設值為 1),建議設定值為 CPU 的數目,但 loading 很大的伺服器可調為 CPU 數的二倍。

將接收的 TCP 連線排入佇列,等待工作緒 (Session Threads) 處理

如前所述,連線被Acceptor 接收後即被丟入 Connection Queue 中,等著被 Session Thread 處理。後方 Session Thread 的執行往往是最花時間的(真正在執行 Servlet/JSP, PHP 等程式碼),所以連線在 Connection Queue 中等待的時間通常會最久。Connection Queue 的大小是由 SJSWS 的 connQueueSize 參數 (預設 4096) 決定。

HTTP 1.1 版有所謂的 Connection Keep Alive 功能,不必每一個 HTTP Request 都重建 TCP Connection,這一類的 Connection 在第一次被 Acceptor 接近來並處理後,就會由 Keep Alive Thread 及單獨的 Poll 接管以處理後續的 HTTP 要求。SJSWS 對於 Keep Alive 機制也有參數可調,如 MaxKeepAliveConnections 指定同時可保留的數目、 KeepAliveTimeout 指定連線最大閒置時間 (防止不負責任的客戶端程式不結束連線) 等。


工作緒處理 Http Request

到此之前,SJSWS 都是在消化及暫存 TCP 連線 ,還沒正真開始處理 HTTP 要求。處理 HTTP 要求是工作緒 (Session Thread) 的責任。

當連線進了 Connection Queue 後,SJSWS 會檢查是否有空閒的 Session Thread 可消化 Queue 中的連線,若有,則將其拉出 Queue 並等給一個空閒的 Session Thread 處理。若沒有空閒的 Session Thread,則會視設定來判定是否要動態增加 Session Thread。Session Thread 的數量等於是伺服器能同時平行處理 HTTP 要求 (通常是指執行 JSP/Servlet) 的能力。Session Thread 的多少是由 SJSWS 的 RqThrottle (預設值為 128) 及 RqThrottleMin (預設值為 48) 來決定。

RqThrottleMin 決定伺服器在剛啟動後或空閒時最少要保持的 Session Thread 數目;RqThrottle 則決定伺服器最多能保有的 Session Thread 數目。調整這個參數要小心,不要太大以免用光系統資源。RqThrottle 是 128,通常不會加到 500 以上。

JVM 處理及回應

Session Thread 是 Language Neutual 的,也就是說 Session Thread 並不是專門處理 JSP/Servlet。在處理 HTTP 要求時,Session Thread 會依據 mine.conf 及 obj.conf 檔中所定義的指令來決定由何種 plug-in (Perl Plug-in, PHP Plug-in, J2EE Plug-in, 或 ReverseProxy Plug-in)來接手。 各種不同型式的 plug-in 也都有自有的調較方法,而且這程調校通常對效能影響最直接也最大。

例如你若用 SJSWS 來佈署 Java Web Application (JSP/Servlet) ,就不要忘記調校 JVM 的設定。最常調的 JVM 設定就是 Heap Memory Size,若 Heap Size 不夠會嚴重影響 Java 程式效能。它的大小由 SJSWS 的 JVMOPTION Xms 及 Xmx來設定。要小心,不要太大,否則易導致 Out of Memeory Exception。

SJSWS 還有很多很多的參數可以調,實在是族繁不及備載。一般在做效能調校時最常要動到的有 :

  • SJS Web Server (以 SJSWS 6.1 為例)
    • JVM Heap size (server.xml)
    • RqThrottle, RqThrottleMin (magnus.conf)
    • connQueueSize (magnus.conf)
    • listenQ (magnus.conf)
    • MaxKeepAliveConnections (magnus.conf)
    • Access & Error Log (server.xml)
  • TCP/IP (以 Solaris 為例)
    • tcp_conn_req_max_q (ndd command)
    • tcp_conn_req_max_q0 (ndd command)
    • tcp_time_wait_interval (ndd command)
    • file descriptor size (etc/system)

效能調校是取捨的藝術,管理者必須決定應該來者不拒(但回應超慢);或是拒絕過多要求(但保持原有連線的服務品質)。盲目地加大參數值只會吃掉資源,但不見得真的會用到 ?

還有,參數和實際效能不是線性關係,只有"合理"的壓測結果才能推估真實的效能。有時會看到效能需求如 "系統應可承受2000人同時使用".....但是沒有服務水準的要求。若平均回應速度慢到 3 分鐘,是否也合乎客戶的要求 ? 還有 "2000 人同時" 的情境要如何在壓測中模擬,也要很小心。2000 Active Users 和 2000 Concurrent Connections 和 2000 Concurrent Requests 是很不一樣的。

About

純粹個人經驗分享,並非官方立場。

Search

Archives
« 四月 2014
星期日星期一星期二星期三星期四星期五星期六
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
今日