最近的項目,面臨情況如下:
1. 并發壓力大。平時并發連接大約在3000左右,高峰期是8000人上線訪問,預期未來會達到20,000人同時在線。
2. 受到網絡攻擊。系統是接在公網上致使網絡爬蟲和攻擊工具都可能給系統帶來未知壓力,甚至突然增加的并發訪問導致系統癱瘓。
3. 數據庫壓力大。有大量的數據庫訪問操作,并且SQL語句中含有COUNT(*)或者JOIN等消耗系統資源的代碼。
為了滿足應用需要,特別對以下環境進行了調優。系統基本配置如下:
HP-UX V11.11 2CPU 4G
HP JDK V1.5
Apusic V5.0
SQL Server 2005
系統硬件條件已經確定,系統資源調用變化最頻繁的就是應用服務器,因此應用服務器所在的操作系統、Java虛擬機(Java Virtual Machine, JVM)和Apusic AS都需要調優。而應用服務器對數據庫的數據庫連接池大小也必定會影響數據庫服務器的相關壓力,因此最后再根據穩定后的應用服務器調整數據庫服務器配置。
1. 先調整JVM。這個先根據JVM所在的應用服務器物理內存的大小和JDK所支持的大小決定,建議是將空閑內存的70%~80%分配給JVM使用。下面是Java啟動時用的配置參數:
-server -Xms1024m -Xmx1024m -Xmn?m -XX:MaxPermSize=256m -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -Xincgc、
注:1. 不同JDK在不同OS下所能使用的內存大小是不同
?2. Heap的大小和分配現在設置的是經驗值,是否調整最終還需要分析應用來定,一般經驗值已經滿足需要。
?3. GC的機制對系統穩定也比較重要,盡可能參考JDK提供的最新GC參數。
?4. 使用server版的JVM一般都會對應用系統提升帶來幫助。
2. 再調整Apusic應用服務器。因為并發壓力大,也意味著系統對CPU和內存的資源消耗都會比較大,為保證應用服務器的穩定修改apusic.conf的配置如下(只保留了修改的部分):
2.1. 線程池調整
?為了平衡用戶訪問速度與并發支持的關系,必須調整Apusic的線程池。調整前依據以下原則:
?● 每CPU50用戶的原則(線程池的設置可參考《Apusic AS V5.1線程池配置和調優》)。
?● HTTPHandler是MuxHandler的三倍。
<SERVICE
??? CLASS="com.apusic.util.ThreadPoolService"
??? NAME="Apusic:service=ThreadPool,name=MuxHandler"
??? >
??? <ATTRIBUTE NAME="MaxThreads" VALUE="100"/>
??? <ATTRIBUTE NAME="MaxSpareThreads" VALUE="30"/>
??? <ATTRIBUTE NAME="MinSpareThreads" VALUE="30"/>
</SERVICE>
<SERVICE
??? CLASS="com.apusic.util.ThreadPoolService"
??? NAME="Apusic:service=ThreadPool,name=HTTPHandler"
??? >
??? <ATTRIBUTE NAME="MaxThreads" VALUE="300"/>
??? <ATTRIBUTE NAME="MaxSpareThreads" VALUE="100"/>
??? <ATTRIBUTE NAME="MinSpareThreads" VALUE="100"/>
</SERVICE>
2.2. Mux(多路復用服務)調優。多路復用是將客戶端的服務申請分發給相應的服務,如:HTTP服務、JMS服務等等。因此該服務對資源占用時間較短,不需要分配太多線程,只需要關注他的接收能力和申請排隊,保證申請不會丟失。
<SERVICE
??? CLASS="com.apusic.net.Muxer"
??? >
??? <ATTRIBUTE NAME="NumberSelectors" VALUE="2"/>
?<!-- 系統CPU核數,多個CPU使用多個Selectors可以加快并發處理能力 -->
??? <ATTRIBUTE NAME="Port" VALUE="80"/>
?<!-- 默認的服務端口 -->
??? <ATTRIBUTE NAME="Backlog" VALUE="50"/>
?<!-- TCP/IP的隊列大小,如果有大量客戶端連接超時,而服務器又沒有足夠的CPU壓力,可以調大這個值 -->
</SERVICE>
2.3. WEB服務調優。
<SERVICE
??? CLASS="com.apusic.web.WebService"
??? >
??? <ATTRIBUTE NAME="NumberSelectors" VALUE="2"/>
?<!-- 系統CPU核數,多個CPU使用多個Selectors可以加快并發處理能力 -->
??? <ATTRIBUTE NAME="MaxKeepAliveConnections" VALUE="300"/>
?<!-- 最大保持KeepAlive的連接數,與HTTPHandler保持一致 -->
??? <ATTRIBUTE NAME="MaxKeepAliveRequests" VALUE="600"/>
?<!-- 最大保持KeepAlive的請求數,設HTTPHandler×2,大約一個連接支持兩次請求,如果服務器硬件條件允許可以再開大些 -->
??? <ATTRIBUTE NAME="WaitingClientTimeout" VALUE="15"/>
??? <ATTRIBUTE NAME="MaxWaitingClients" VALUE="200"/>
?<!-- 等待隊列滿了后,將客戶端請求拋棄的等待時間。如果關注系統反應的及時性,就把這個值調小,還可以把請求隊列MaxWaitingClients調??;如果關注系統服務的有效性則要調大。-->
??? <ATTRIBUTE NAME="KeepAlive" VALUE="True"/>
?<!-- 默認打開KeepAlive,了解這個參數配置需要參看HTTP 1.1協議 -->
??? <ATTRIBUTE NAME="ServletReloadCheckInterval" VALUE="-1"/>
?<!-- 設為-1,意思就是不檢查,因為這個功能是為開發階段提供熱部署的 -->
??? <ATTRIBUTE NAME="KeepAliveTimeout" VALUE="15"/>
?<!-- 服務器關閉客戶端連接前等待下一次請求的時間,如果系統壓力較大可以將這個值設小,以便應對更多的請求。 -->
</SERVICE>
2.3. Session服務
基本上采用默認值就可以了,如果需要配置集群才需要調整Session里面某些配置選項,具體可以參考Apusic集群配置。
2.4. 數據庫連接池服務
<datasources>
? <datasource name="test"
???? jndi-name="jdbc/test"
???? driver-class="net.sourceforge.jtds.jdbc.Driver"
???? url="Jdbc:jtds:sqlserver://192.168.0.1:1433/test"
???? min-spare-connections="50"
???? max-spare-connections="50"
???? max-connections="150"
???? initial-connections="50"
? >
??? <property name="user" value="sa"/>
??? <property name="test-before-reused" value="false"/>
??? <property name="password" value="test"/>
??? <property name="stmt-cache-size" value="50"/>
??? <property name="pre-fetch-size" value="50"/>
? </datasource>
</datasources>
min-spare-connections、max-spare-connections:在池中保留的空閑數據庫連接數;
initial-connections:初始化的空閑數據庫連接數;
三個值相同,保證在初始化時就有足夠的數據庫連接使用。
數據庫連接數×2=HTTP線程池數目
注:max-connections在現實中被調小。因為數據庫服務器無法處理更多響應,因此原則是先保證擁有數據庫連接的線程能夠有效響應。
3. 調整HP-UX操作系統。
3.1. 首先調整核心資源,使用ulimit -a查看核心參數,特別關注file和memory兩部分的使用,有些時候操作系統限制了進程打開文件數和內存使用數,無法有效利用硬件資源也會限制應用服務器性能的發揮。
3.2. 因為應用系統受到攻擊,致使出現大量的CLOSE_WAIT、FIN_WAIT_2這樣狀態的連接,消耗大量系統資源。因此使用ndd進行網絡參數配置,先用:ndd /dev/tcp,然后輸入?,可以得到所有網絡參數情況。使用:ndd -get /dev/tcp 參數名稱,可以獲得原參數的值。使用:ndd -set /dev/tcp 參數名稱 參數值,可以設置新參數的值。例如:獲得初始值:ndd -get /dev/tcp tcp_time_wait_interval,設置新值:ndd -set /dev/tcp tcp_time_wait_interval 30000,30000是毫秒單位=30秒。不能設置為0,0似乎是無限長的意思。需要關注的參數如下:
#與TIME_WAIT相關的參數,當系統出現大量此狀態的連接時可以調小這個值
tcp_time_wait_interval ??30000
tcp_tw_cleanup_interval ?60000
#與FIN_WAIT相關的參數
tcp_fin_wait_2_timeout? ?1000
#與KeepAlive相關的參數,因為應用服務器不負責KeepAlive連接的管理,因此這里由操作系統負責
tcp_keepalive_interval ??120000
tcp_keepalive_detached_interval?120000
tcp_keepalives_kill ??1
tcp_ip_abort_interval ??600000
#與TCP連接數相關的參數
tcp_conn_request_max ??4096
注:使用ndd重新啟動后就無效了。可以修改/etc/rc.config.d/nddconf就可以在機器重新啟動時有效。
4. 調整SQL Server數據庫的參數。這個是因為數據庫壓力較大,才關注到這個部分調優。
4.1. 內存調整。因為SQL Server內存管理默認無限大,結果把系統資源全部耗盡,因此將服務器內存按照70~80%原則分配給SQL Server使用。
4.2. 處理器設置。主要是選擇提升SQL Server的優先級和使用Windows纖程,保證SQL Server在操作系統中的執行速度。
4.3. 連接設置??刂谱畲蟛l連接數,比數據庫連接池所設的連接數稍大就可以了,防止過多連接導致系統切換線程帶來的資源消耗。同時合理設置查詢的超時時間,保證資源不會被某個訪問占用。
4.4. 活動監視器。通過活動監視器查看系統中的活動進程,以及執行的SQL語句,并且在系統壓力較大時觀察是否有資源被鎖。
?不過這些其實都只是幫助系統更好的運行,實際上SQL Server資源消耗問題的解決仍然領先應用的調整,應用發現某些表關聯有問題,重新調整后CPU壓力立刻降低。
?以上是整個調優的過程記錄。