在前兩天的學習中咱們知道、瞭解並掌握了Web Server結合App Server實現單向Https的這樣的一個架構。這個架構是一個很是基礎的J2ee工程上線佈署時的一種架構。在前兩天的教程中,還講述了Http服務器、App Server的最基本安全配置(包括單向https的實現), 它只是避免了用戶能夠經過瀏覽器侵入咱們的Web訪問器或者可以經過Web瀏覽器來查詢咱們的Web目錄結構及其目錄內的文件與相關內容,這種入侵咱們把它稱爲:javascript
Directory traversal,固然咱們只是實現了最基本的防範Directory traversal的手段,在往後的Security課程中將會詳細地去擅述完整的Web Security的相關理論。php
從今天起咱們將繼續在原有的這種Apache+Tomat的架構上,去論述如何在性能及Performance上優化這個架構,所以這兩天的課程在有些人看來,可能會有些「枯燥」,因此我在此給你們打個招呼:css
這兩天的課程論述的是如何在不改動代碼與SQL語句的前提下,如何去改善和提升web server與app server的性能,千萬不要小覷這一內容,它可讓你在不改動代碼的狀況下獲得10-20倍以上的性能提升,網上有其它的大牛們寫過一篇文章叫「Tomcat如何支持到1000個用戶」,經本人通過幾個重大工程的實踐,Opensource的Tomcat若是調優的好不僅能夠支持者1000個用戶,尤爲當你的佈署環境是64位操做系統的狀況下,可能可以支持更大更高的併發性能,最後本節內容將會以Tomcat集羣來作收場,在未來的課程中還會進一步詳細講述Weblogic的集羣配置與IBM WASND的集羣配置。html
即壓力測試,就是根據必定數量的VU(Virtual Users)我稱爲併發用戶操做核心交易後,系統所能達到的最大瓶勁,以便於發現系統的極限、有沒有Outof memory這樣的問題存在以及相關的系統設置、配置是否搭擋的合理的一種測試。前端
通常商業的比較好的用LoaderRunner,若是沒錢的就用Opensource的Jmeter來模擬這個VU的操做。java
壓力測試,存在幾個誤區,須要當心。web
1) 無限大的拼命增長VU的數量數據庫
系統再完美,硬件配置再高,也經不住沒有通過合理運算的VU的壓力呀。apache
2) 偏執的用必定的數據量的VU,跑7*24小時瀏覽器
不是說這個不必,頗有必要,小日本的電視爲何壽命敢說比中國人生產的電視機壽命長?由於它用一個機械臂就對着電視機的按鈕不斷的點點點。
咱們說的壓力測試要測試多長時間,關鍵是要看通過科學計算的VU的數量以及核心交易數有多少,不是說我拿250個VU跑24*7若是沒有問題我這個系統就沒有問題了,這樣的說法是不對的,錯誤的。隨便舉個例子就能把你推倒。
假設我有250個VU,同時跑上萬筆交易,每一個VU都有上萬筆交易,250個VU一次跑下來可能就要數個小時,你又怎麼能判定250個VU對於這樣的系統我跑24*7小時就能真的達到上萬筆交易在250個VU的併發操做下可以真的跑完7天的所有交易?可能須要一週半或者兩週呢?對吧?
我還看到過有人拿500個VU對着一條交易反覆跑24*7小時。。。這樣的測試有意義嗎?你係統就僅僅只有一條交易?你怎麼可以判斷這條交易涉及到的數據量最大?更不用說交易是彼此間有依賴的,可能a+b+c+d的交易的一個混合組織就可以超出你單筆交易所涉及到的數據量了呢!
提供下面這個公式,以供你們在平時或者平常須要進行的性能測試中做爲一個參考。
(1) 計算平均的併發用戶數:C = nL/T
公式(1)中,C是平均的併發用戶數;n是login session的數量;L是login session的平均長度;T指考察的時間段長度。
(2) 併發用戶數峯值:C’ ≈ C+3根號C
公式(2)則給出了併發用戶數峯值的計算方式中,其中,C’指併發用戶數的峯值,C就是公式(1)中獲得的平均的併發用戶數。該公式的得出是假設用戶的loginsession產生符合泊松分佈而估算獲得的。
實例:
假設有一個OA系統,該系統有3000個用戶,平均天天大約有400個用戶要訪問該系統,對一個典型用戶來講,一天以內用戶從登陸到退出該系統的平均時間爲4小時,在一天的時間內,用戶只在8小時內使用該系統。
則根據公式(1)和公式(2),能夠獲得:
C = 400*4/8 = 200
C’≈200+3*根號200 = 242
F=VU * R / T
其中F爲吞吐量,VU表示虛擬用戶個數,R表示每一個虛擬用戶發出的請求數,T表示性能測試所用的時間
R = T / TS。
從上面的公式一節中咱們還獲得了一個名詞「吐吞量」。和吞吐量相關的有下面這些概念,記錄下來以供參考。
² 吞吐量
指在一次性能測試過程當中網絡上傳輸的數據量的總和。
對於交互式應用來講,吞吐量指標反映的是服務器承受的壓力,在容量規劃的測試中,吞吐量是一個重點關注的指標,由於它可以說明系統級別的負載能力,另外,在性能調優過程當中,吞吐量指標也有重要的價值。
² 吞吐率
單位時間內網絡上傳輸的數據量,也能夠指單位時間內處理客戶請求數量。它是衡量網絡性能的重要指標,一般狀況下,吞吐率用「字節數/秒」來衡量,固然,你能夠用「請求數/秒」和「頁面數/秒」來衡量。其實,無論是一個請求仍是一個頁面,它的本質都是在網絡上傳輸的數據,那麼來表示數據的單位就是字節數。
² 事務
就是用戶某一步或幾步操做的集合。不過,咱們要保證它有一個完整意義。好比用戶對某一個頁面的一次請求,用戶對某系統的一次登陸,淘寶用戶對商品的一次確認支付過程。這些咱們均可以看做一個事務。那麼如何衡量服務器對事務的處理能力。又引出一個概念----TPS
² TPS (Transaction Per second)
每秒鐘系統可以處理事務或交易的數量,它是衡量系統處理能力的重要指標。
² 點擊率(Hit Per Second)
點擊率能夠看作是TPS的一種特定狀況。點擊率更能體現用戶端對服務器的壓力。TPS更能體現服務器對客戶請求的處理能力。
每秒鐘用戶向web服務器提交的HTTP請求數。這個指標是web 應用特有的一個指標;web應用是「請求-響應」模式,用戶發一個申請,服務器就要處理一次,因此點擊是web應用可以處理的交易的最小單位。若是把每次點擊定義爲一個交易,點擊率和TPS就是一個概念。容易看出,點擊率越大。對服務器的壓力也越大,點擊率只是一個性能參考指標,重要的是分析點擊時產生的影響。
須要注意的是,這裏的點擊不是指鼠標的一次「單擊」操做,由於一次「單擊」操做中,客戶端可能向服務器發現多個HTTP請求。
² 吞吐量指標的做用:
ü 用戶協助設計性能測試場景,以及衡量性能測試場景是否達到了預期的設計目標:在設計性能測試場景時,吞吐量可被用戶協助設計性能測試場景,根據估算的吞吐量數據,能夠對應到測試場景的事務發生頻率,事務發生次數等;另外,在測試完成後,根據實際的吞吐量能夠衡量測試是否達到了預期的目標。
ü 用於協助分析性能瓶頸:吞吐量的限制是性能瓶頸的一種重要表現形式,所以,有針對性地對吞吐量設計測試,能夠協助儘快定位到性能冰晶所在位置。
² 平均相應時間
也稱爲系統響應時間,它通常指在指定數量的VU狀況下,每筆交易從mouse 的click到IE的數據刷新與展現之間的間隔,好比說:250個VU下每筆交易的響應時間不超過2秒。
固然,響應時間也不能一律而論,對於實時交易若是銀行櫃檯操做、超市收銀員(邪惡的笑。。。)的操做、證交所交易員的操做來講這些操做的響應時間固然是越快越好,而對於一些企業級的如:
與銀行T+1交易間的數據跑批、延時交易、T+1報表等,你要求它在2秒內響應,它也作不到啊。就比如你有個1MB的帶寬,你傳的東西是超過4MB,你要它在2秒內跑完理論速度也作不到啊,對吧,因此有些報表或者數據,光前面傳輸時間就不止兩秒了。。。一口咬死說我全部的交易平均相應時間要2秒,真的是不科學的!
² VU數量的增長
一個合理的性能測試除了須要合理的計算VU的數量、合理的設置系統平均響應時間外還須要合理的在測試時去規劃發起VU的時間,好比說,我看到有人喜歡這樣作壓力測試。
第一秒時間,500個併發用戶所有發起了。。。結果致使系統沒多久就崩了,而後說系統沒有知足設計要求。
爲何說上述這樣的作法是不對的?咱們說不是徹底不對,只能說這樣的測試已經超過了500個VU的併發的設計指標了。
合理的併發應該是以下這樣的:
有25-50個VU開始起交易了,而後過一段時間又有25-50個用戶,過一段時間又增長一些VU,當全部的設計VU都發起交易了,此時,再讓壓力測試跑一段時間好比說:24*7是比較合理的。因此VU數量不是一上手就500個在一秒內發起的,VU數量的增長應該以下面這張趨勢圖:
這是一個階梯狀的梯型圖,能夠看到VU的發起是逐漸逐漸增多的,如下兩種狀況若是發生須要檢查你的系統是否在原有設置上存在問題:
ü VU數量上升階段時崩潰
有時僅僅在VU數量上升階段,系統就會了現各類各樣的錯誤,甚至有崩潰者,這時就有從新考慮你的系統是否有設置不合理的地方了。
ü VU所有發起後沒多久系統崩潰
VU在達到最高值時即全部的VU都已經發起了,此時它是以一條直的水平線隨着系統運行而向前延伸着的,但過不了多久,好比說:運行24*7小時,運行了沒1、兩天,系統崩潰了,也須要作檢查。
因此,理想的性能測試應該是VU數量上升到最終VU從發起開始到最後全部VU把交易作完後,VU數量落回零爲止。
² 吐吞量的變化
從2.3節咱們能夠知道,吞吐量是隨着壓力/性能測試的時間而逐漸增大的,所以你的吞吐量指示應該以下圖所示:
確定是這樣,你的吞吐量因該是積累的,若是你的吞吐量在上升了一段時間後忽然下落,而此時你的性能測試還在跑着,以下圖所示:
那麼,此時表明什麼事情發生了?你能夠查一下你的loaderrunner或者jmeter裏對於這段吞吐量回落期間的交易的response的狀態進行查看,你將會發現大量的error已經產生,由於產生了error,因此你的交易其實已經出錯了,所以每次運行的數據量愈來愈小,這也就意味着你的壓力測試沒有過關,系統被你壓崩了!
² 平均響應時間
平均響應時間如VU的數量增長趨勢圖同樣,必定是一開始響應時間最短,而後一點點增高,當增高到必定的程度後,即全部的VU都發起交易時,你的響應時間應該維持在一個水平值,而後隨着VU將交易都一筆筆作完後,這個響應時間就會落下來,這段時間內的平均值就是你的系統平均響應時間。看看它,有沒有符合設計標準?
² 內存監控
咱們就來講AppServer,咱們這邊用的是Tomcat即SUN的JVM的內存變化,咱們就用兩張圖例來說解吧:
理想狀態狀況下的JVM內存使用趨勢:
這是一個波浪型的(或者也能夠說是鋸齒型的)趨勢圖,隨着VU數量的一點點增長,咱們的內存使用數會不斷的增長,可是JVM的垃圾回收是自動回收機制的,所以若是你的JVM如上述樣的趨勢,內存上漲一段時間,隨即會一點點下落,而後再上漲一點,漲到快到頭了又開始下落,直到最後你的VU數量所有降低下來時,你的JVM的內存使用也會一點點的降低。
非理想狀態狀況下的JVM內存使用趨勢:
嘿嘿嘿,看到了嗎?你的JVM隨着VU 數量的上升,而直線上升,而後到了必定的點後,即到了java –Xmx後的那個值後,忽然直線回落,而此時你的交易還在進行,壓力測試也還在進行,但是內存忽然回落了。。。由於你的JVM已經crash了,即OUT OF MEMORY鳥。
² CPU Load
咱們來看一份測試人員提交上來CPU得用率的報告:
Web Server |
App Server |
DB Server |
60% |
98% =_=!(oh my god) |
6% 囧 |
同時平均響應時間好慢啊。
拿過來看了一下代碼與設計。。。Struts+Spring+JDBC的一個框架,沒啥花頭的,再仔細一看Service層。
大量的複雜業務邏輯甚至報表的產生所有用的是javaobject如:List, Hashmap等操做,甚至還有在Service層進行排序、複雜查詢等操做。
一看DB層的CPU利用率才6%,將一部分最複雜的業務拿出去作成Store Procedure(存儲過程後),再從新運行壓力測試。
Web Server |
App Server |
DB Server |
60% |
57% =_=!(oh my god) |
26% 囧 |
同時平均響應時間比原來快了15-16倍。
爲何??
看看第一份報告,咱們當時還查看了數據庫服務器的配置,和APPServer的配置是一個級別的,而利用率才6%。。。
數據庫,至因此是大型的商用的關係型數據庫,你只拿它作一個存儲介質,你這不是浪費嗎?人家裏面設置的這個StoreProcedure的處理能力,索引效率,數據分塊等功能都沒有去利用,而用你的代碼去實現那麼多複雜業務好比說多表關聯、嵌套等操做,用必要嗎?那要數據庫幹什麼用呢?
是啊,我認可,原有這樣的代碼,跨平臺能力強一點,可付出的代價是什麼呢?
用戶在意你所謂的跨平臺的理論仍是在意的是你係統的效率?一個系統定好了用DB2或者是SQL SERVER,你以爲過一年它會換成ORACLE或者MYSQL嗎?若是1年一換,那你作的系統也只能讓用戶勉強使用一年,我勸你仍是不要去作了。在中國,有人統計過5年左右會有一次系統的更換,而一些銀行、保險、金融行業的系統一旦採用了哪一個數據庫,除非這個系統完全出了問題,負責是不會輕意換數據庫的,所以不要拿所謂的純JAVA代碼或者說我用的是Hibernate,ejb實現能夠跨數據庫這套來講事,效率低下的系統能夠否認你所作的一切,一切!
上面兩節,講了大量的理論與實際工做中碰到的相關案例,如今就來說一下在咱們第一天和次日中的ApacheHttp Server + Tomcat這樣的架構,怎麼來作優化吧。
Apache Http Server在剛安裝完後是沒有併發數的控制的,它採用一個默認的值,那麼咱們的Web Server硬件很好,容許咱們撐到1000個併發即VU,而由於咱們沒有去配置致使咱們的WebServer連300個併發都撐不到,大家認爲,這是誰的責任?
Apache Http服務器採用prefork或者是worker兩種併發控制模式。
² preforkMPM
使用多個子進程,每一個子進程只有一個線程。每一個進程在某個肯定的時間只能維持一個鏈接。在大多數平臺上,PreforkMPM在效率上要比Worker MPM要高,可是內存使用大得多。prefork的無線程設計在某些狀況下將比worker更有優點:它可使用那些沒有處理好線程安全的第三方模塊,而且對於那些線程調試困難的平臺而言,它也更容易調試一些。
² workerMPM 使用多個子進程,每一個子進程有多個線程。每一個線程在某個肯定的時間只能維持一個鏈接。一般來講,在一個高流量的HTTP服務器上,Worker MPM是個比較好的選擇,由於Worker MPM的內存使用比PreforkMPM要低得多。但worker MPM也由不完善的地方,若是一個線程崩潰,整個進程就會連同其全部線程一塊兒"死掉".因爲線程共享內存空間,因此一個程序在運行時必須被系統識別爲"每一個線程都是安全的"。
通常來講咱們的ApacheHttp Server都是裝在Unix/Linux下的,並且是採用源碼編譯的方式來安裝的,咱們可以指定在編譯時Apache就採用哪一種模式,爲了明確咱們目前的Apache採用的是哪一種模式在工做,咱們還可使用httpd –l命令即在Apache的bin目錄下執行httpd –l,來確認咱們使用的是哪一種模式。
這邊,咱們使用Apache配置語言中的」 IfModule」來自動選擇模式的配置。
咱們的ApacheHttp Server在配完後通常是沒有這樣的配置的,是須要你手動的添加以下這樣的一塊內容的,咱們來看,在httpd.conf文件中定位到最後一行LoadModule,敲入回車,加入以下內容:
<IfModule prefork.c> ServerLimit 20000 StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxClients 1000 MaxRequestsPerChild 0 </IfModule> |
上述參數解釋:
ü ServerLimit 20000
默認的MaxClient最大是256個線程,若是想設置更大的值,就的加上ServerLimit這個參數。20000是ServerLimit這個參數的最大值。若是須要更大,則必須編譯apache,此前都是不須要從新編譯Apache。
生效前提:必須放在其餘指令的前面
ü StartServers 5
指定服務器啓動時創建的子進程數量,prefork默認爲5。
ü MinSpareServers 5
指定空閒子進程的最小數量,默認爲5。若是當前空閒子進程數少於MinSpareServers ,那麼Apache將以最大每秒一個的速度產生新的子進程。此參數不要設的太大。
ü MaxSpareServers 10
設置空閒子進程的最大數量,默認爲10。若是當前有超過MaxSpareServers數量的空閒子進程,那麼父進程將殺死多餘的子進程。此參數不要設的太大。若是你將該指令的值設置爲比MinSpareServers小,Apache將會自動將其修改爲"MinSpareServers+1"。
ü MaxClients 256
限定同一時間客戶端最大接入請求的數量(單個進程併發線程數),默認爲256。任何超過MaxClients限制的請求都將進入等候隊列,一旦一個連接被釋放,隊列中的請求將獲得服務。要增大這個值,你必須同時增大ServerLimit。
ü MaxRequestsPerChild10000
每一個子進程在其生存期內容許伺服的最大請求數量,默認爲10000.到達MaxRequestsPerChild的限制後,子進程將會結束。若是MaxRequestsPerChild爲"0",子進程將永遠不會結束。
將MaxRequestsPerChild設置成非零值有兩個好處:
1.能夠防止(偶然的)內存泄漏無限進行,從而耗盡內存。
2.給進程一個有限壽命,從而有助於當服務器負載減輕的時候減小活動進程的數量。
Prefork.c的工做方式:
一個單獨的控制進程(父進程)負責產生子進程,這些子進程用於監聽請求並做出應答。Apache老是試圖保持一些備用的(spare)或者是空閒的子進程用於迎接即將到來的請求。這樣客戶端就不須要在獲得服務前等候子進程的產生。在Unix系統中,父進程一般以root身份運行以便邦定80端口,而Apache產生的子進程一般以一個低特權的用戶運行。User和Group指令用於設置子進程的低特權用戶。運行子進程的用戶必需要對它所服務的內容有讀取的權限,可是對服務內容以外的其餘資源必須擁有儘量少的權限。
在上述的</IfModule>後再加入一個」<IfModule>」以下紅色加粗(大又粗)內容:
<IfModule prefork.c> ServerLimit 20000 StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxClients 1000 MaxRequestsPerChild 0 </IfModule> <IfModule worker.c> ServerLimit 50 ThreadLimit 200 StartServers 5 MaxClients 5000 MinSpareThreads 25 MaxSpareThreads 500 ThreadsPerChild 100 MaxRequestsPerChild 0 </IfModule> |
上述參數解釋:
ü ServerLimit16
服務器容許配置的進程數上限。這個指令和ThreadLimit結合使用設置了MaxClients最大容許配置的數值。任何在重啓期間對這個指令的改變都將被忽略,但對MaxClients的修改卻會生效。
ü ThreadLimit64
每一個子進程可配置的線程數上限。這個指令設置了每一個子進程可配置的線程數ThreadsPerChild上限。任何在重啓期間對這個指令的改變都將被忽略,但對ThreadsPerChild的修改卻會生效。默認值是"64".
ü StartServers3
服務器啓動時創建的子進程數,默認值是"3"。
ü MinSpareThreads75
最小空閒線程數,默認值是"75"。這個MPM將基於整個服務器監視空閒線程數。若是服務器中總的空閒線程數太少,子進程將產生新的空閒線程。
ü MaxSpareThreads250
設置最大空閒線程數。默認值是"250"。這個MPM將基於整個服務器監視空閒線程數。若是服務器中總的空閒線程數太多,子進程將殺死多餘的空閒線程。MaxSpareThreads的取值範圍是有限制的。Apache將按照以下限制自動修正你設置的值:worker要求其大於等於MinSpareThreads加上ThreadsPerChild的和
ü MaxClients400
容許同時伺服的最大接入請求數量(最大線程數量)。任何超過MaxClients限制的請求都將進入等候隊列。默認值是"400",16(ServerLimit)乘以25(ThreadsPerChild)的結果。所以要增長MaxClients的時候,你必須同時增長ServerLimit的值。
ü ThreadsPerChild25
每一個子進程創建的常駐的執行線程數。默認值是25。子進程在啓動時創建這些線程後就再也不創建新的線程了。
ü MaxRequestsPerChild 0
設置每一個子進程在其生存期內容許伺服的最大請求數量。到達MaxRequestsPerChild的限制後,子進程將會結束。若是MaxRequestsPerChild爲"0",子進程將永遠不會結束。
將MaxRequestsPerChild設置成非零值有兩個好處:
1.能夠防止(偶然的)內存泄漏無限進行,從而耗盡內存。
2.給進程一個有限壽命,從而有助於當服務器負載減輕的時候減小活動進程的數量。
注意
對於KeepAlive連接,只有第一個請求會被計數。事實上,它改變了每一個子進程限制最大連接數量的行爲。
Worker.c的工做方式:
每一個進程能夠擁有的線程數量是固定的。服務器會根據負載狀況增長或減小進程數量。一個單獨的控制進程(父進程)負責子進程的創建。每一個子進程能夠創建ThreadsPerChild數量的服務線程和一個監聽線程,該監聽線程監聽接入請求並將其傳遞給服務線程處理和應答。Apache老是試圖維持一個備用(spare)或是空閒的服務線程池。這樣,客戶端無須等待新線程或新進程的創建便可獲得處理。在Unix中,爲了可以綁定80端口,父進程通常都是以root身份啓動,隨後,Apache以較低權限的用戶創建子進程和線程。User和Group指令用於設置Apache子進程的權限。雖然子進程必須對其提供的內容擁有讀權限,但應該儘量給予它較少的特權。另外,除非使用了suexec,不然,這些指令設置的權限將被CGI腳本所繼承。
公式:
ThreadLimit>= ThreadsPerChild
MaxClients <= ServerLimit * ThreadsPerChild 必須是ThreadsPerChild的倍數
MaxSpareThreads>= MinSpareThreads+ThreadsPerChild
硬限制:
ServerLimi和ThreadLimit這兩個指令決定了活動子進程數量和每一個子進程中線程數量的硬限制。要想改變這個硬限制必須徹底中止服務器而後再啓動服務器(直接重啓是不行的)。
Apache在編譯ServerLimit時內部有一個硬性的限制,你不能超越這個限制。
preforkMPM最大爲"ServerLimit200000"
其它MPM(包括work MPM)最大爲"ServerLimit 20000
Apache在編譯ThreadLimit時內部有一個硬性的限制,你不能超越這個限制。
mpm_winnt是"ThreadLimit 15000"
其它MPM(包括work prefork)爲"ThreadLimit 20000
注意
使用ServerLimit和ThreadLimit時要特別小心。若是將ServerLimit和ThreadLimit設置成一個高出實際須要許多的值,將會有過多的共享內存被分配。當設置成超過系統的處理能力,Apache可能沒法啓動,或者系統將變得不穩定。
以上是Linux/Unix下的Apache的併發數優化配置,若是咱們打入了httpd –l以下顯示:
怎麼辦?
ü 步驟一
先修改/path/apache/conf/httpd.conf文件。
httpd.conf
將「#Includeconf/extra/httpd-mpm.conf」前面的 「#」 去掉,保存。
ü 步驟二
再修改/apache安裝目錄/conf/extra/httpd-mpm.conf文件。
在mpm_winnt模式下,Apache不使用prefork也不使用work工做模式,切記!
所以,咱們只要找到原文件中:
<IfModule mpm_winnt_module> ThreadsPerChild 150 MaxRequestsPerChild 0 </IfModule> |
修改後
<IfModule mpm_winnt_module> ThreadsPerChild 500 MaxRequestsPerChild 5000 </IfModule> |
上述參數解釋:
ü ThreadsPerChild
是指一個進程最多擁有的線程數(Windows版本,貌似不能夠開啓多個進程),通常100-500就能夠,根據服務器的具體性能來決定。
ü MaxRequestsPerChild
是指一個線程最多能夠接受的鏈接數,默認是0,就是不限制的意思,
0極有可能會致使內存泄露。因此,能夠根據實際狀況,配置一個比較大的值。Apache會在幾個線程之間進行輪詢,找到負載最輕的一個線程來接受新的鏈接。
注意:
修改後,必定不要apacherestart,而是先 apache stop 而後再 apache start才能夠。
對於靜態的html 文件,在apache 可加載mod_deflate.so 模塊,把內容壓縮後輸出,可節約大量的傳輸帶寬。
打開httpd.conf文件,找到:
#LoadModule deflate_module modules/mod_deflate.so |
將前面的「#」去掉,變成:
LoadModule deflate_module modules/mod_deflate.so |
而後在最後一行的LoadModule處,加入以下的幾行:
<IfModule mod_deflate.c> DeflateCompressionLevel 7 AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-httpd-php AddOutputFilter DEFLATE css js </IfModule> |
注意:
默認等級是6,並且9級須要更多的CPU時間,用默認的6級就能夠了。
要注意的是,在apache 2.2.15中,我用httpd -l看,竟然發現mod_deflat已經內置了,因此其實就不用再在httpd.conf中增長loadmodule了,不然會說出錯的
咱們常常會在web頁的一個超連接上點一個指向物理文件的文檔,咱們通常會獲得「保存,另存爲,打開」,3個選項,當咱們打開的若是是一個MS文檔,在選「打開」選項時IE會自動啓用客戶端上裝有的word或者是excel等相關MS辦公工具去打開,這個怎麼作呢?很簡單。
打開httpd.conf,找到:
AddType application/x-compress .Z AddType application/x-gzip .gz .tgz |
在其後敲入一個回車,加入:
AddType application/vnd.openxmlformats docx pptx xlsx doc xls ppt txt |
重啓Apache服務便可。
DDOS攻擊即採用自動點擊機器人或者連續點擊工具不斷的刷新某一個網址或者網頁上的按鈕,形成網站在一時間收到大量的HTTP請求,進而阻塞網站正常的HTTP通道甚至形成網站癱瘓。
爲了防止這一形式的攻擊,咱們通常把在一個按鈕或者是一個請求在一秒內連續執行如:100次,能夠認爲是一種攻擊(好比說你打開一個網頁,點一下提交按鈕,而後按住F5鍵不鬆開)。
在Linux下的Apache HttpServer安裝後會提供一個mod_evasive20的模塊,用於防止這一形式的攻擊,它的作法是:
若是認爲是一個DDOS攻擊,它的防範手段採用以下兩種形勢:
ü 把這個請求相關聯的IP,封鎖30分鐘
ü 直接把相關的IP踢入黑名單,讓其永不翻身
設置:
在你的Apache的httpd.conf文件中的最後一行「LoadModule」加入以下這句:
LoadModule evasive20_module /usr/lib/httpd/modules/mod_evasive20.so |
而後加入下面這幾行
<IfModule mod_evasive20.c> DOSHashTableSize 3097 DOSPageCount 15 DOSSiteCount 100 DOSPageInterval 1 DOSSiteInterval 1 DOSBlockingPeriod 36000 DOSEmailNotify 網站超級管理員@xxx.com DOSLogDir "logs/mod_evasive" </IfModule> |
核心參數解釋:
ü DOSHashTableSize3097 記錄黑名單的尺寸
ü DOSPageCount 每一個頁面被判斷爲dos攻擊的讀取次數
ü DOSSiteCount 每一個站點被判斷爲dos攻擊的讀取部件(object)的個數
ü DOSPageInterval 讀取頁面間隔秒
ü DOSSiteInterval 讀取站點間隔秒
ü DOSBlockingPeriod 被封時間間隔秒
注意:
上述設置是針對Linux/Unix下的Apache Server,相關的Windows下的Apache見以下設置:
爲Windows下的Apache加載mod_evasive模塊
1. 下載附件中的壓縮包,解壓並拷貝mod_dosevasive22.dll到Apache安裝目錄下的modules目錄(固然也能夠是其餘目錄,須要本身修改路徑)。
2. 修改Apache的配置文件http.conf。
添加如下內容
LoadModule dosevasive22_module modules/mod_dosevasive22.dll DOSHashTableSize 3097 DOSPageCount 3 DOSSiteCount 50 DOSPageInterval 1 DOSSiteInterval 1 DOSBlockingPeriod 10 |
這個話題頗有趣,原由是咱們在工程中碰到了客戶這樣的一個需求:
<a href=」xxx.xxx.xx/xx/xxx/輪胎損壞狀況2007-05-05.jpg」>損壞部件</a>
看看好像沒啥問題,一點這個超連接,因該是在IE中打開一個叫」 輪胎損壞狀況2007-05-05.jpg」,嘿嘿,你們本身動手放一個帶有中文名的這樣的一個圖片,看看可否被解析,解析不了。
因此咱們就說,真奇怪,咱們上傳圖片都是上傳時的圖片名經上傳組件解析過之後變成一個UUID或者是GUID一類的文件名如:gb19070122abcxd.jpg這樣一種英文加數字組合的文件名,這樣的文件名,Apache固然是能夠解析的,客戶堅持必定我上傳的圖片是中文名(連中文描述都不行),由於,客戶說:咱們是中國人,固然用中文圖片名。。。
沒辦法,找了半天,找到一篇日文的教程,還好還好,N年前學過一點點日語,照着教程把它啃下來了。
這是一個日本人寫的關於在Apache中支持以亞州文字命名文件名的一個「補丁」,叫「mod_encoding」。
相關配置:
1. 下載完後是一個這樣的壓縮包:mod_encoding-20021209.tar.gz
2. 解壓後使用:
configure make make install |
在make這一行時,編譯出錯,報「make: *** [mod_encoding.so] Error 1」這樣的錯
緣由很明顯,是regex.h未包含進來,解決辦法也很簡單:
ü 用vi打開mod_encoding.c,
ü 在#include <httpd.h>那一段的前面加上以下一行:
#include <regex.h>而後:
從新make再make install 搞定,CALL!!!
3. 編譯後獲得一個:mod_encoding.so的文件,而後在httpd.conf文件中加入下面這幾行:
LoadModule encoding_module modules/mod_encoding.so Header add MS-Author-Via "DAV" <IfModule mod_encoding.c> EncodingEngine on NormalizeUsername on SetServerEncoding GBK DefaultClientEncoding UTF-8 GBK GB2312 AddClientEncoding "(Microsoft .* DAV $)" UTF-8 GBK GB2312 AddClientEncoding "Microsoft .* DAV" UTF-8 GBK GB2312 AddClientEncoding "Microsoft-WebDAV*" UTF-8 GBK GB2312 </IfModule> |
4. 重啓Apache,搞定,在apache中咱們的url能夠是中文名的附件了。
在Apache 服務器中,KeepAlive是一個布爾值,On 表明打開,Off 表明關閉,這個指令在其餘衆多的 HTTPD 服務器中都是存在的。
KeepAlive 配置指令決定當處理完用戶發起的 HTTP 請求後是否當即關閉 TCP 鏈接,若是 KeepAlive 設置爲On,那麼用戶完成一次訪問後,不會當即斷開鏈接,若是還有請求,那麼會繼續在這一次 TCP 鏈接中完成,而不用重複創建新的 TCP 鏈接和關閉TCP 鏈接,能夠提升用戶訪問速度。
那麼咱們考慮3種狀況:
1.用戶瀏覽一個網頁時,除了網頁自己外,還引用了多個javascript 文件,多個css 文件,多個圖片文件,而且這些文件都在同一個HTTP 服務器上。
2.用戶瀏覽一個網頁時,除了網頁自己外,還引用一個javascript 文件,一個圖片文件。
3.用戶瀏覽的是一個動態網頁,由程序即時生成內容,而且不引用其餘內容。
對於上面3中狀況,我認爲:1 最適合打開 KeepAlive ,2 隨意,3 最適合關閉 KeepAlive
下面我來分析一下緣由。
在 Apache 中,打開和關閉 KeepAlive 功能,服務器端會有什麼異同呢?
先看看理論分析。
打開KeepAlive 後,意味着每次用戶完成所有訪問後,都要保持必定時間後才關閉會關閉TCP 鏈接,那麼在關閉鏈接以前,必然會有一個Apache進程對應於該用戶而不能處理其餘用戶,假設KeepAlive 的超時時間爲10 秒種,服務器每秒處理 50個獨立用戶訪問,那麼系統中 Apache 的總進程數就是 10 * 50 = 500 個,若是一個進程佔用 4M 內存,那麼總共會消耗 2G內存,因此能夠看出,在這種配置中,至關消耗內存,但好處是系統只處理了 50次 TCP 的握手和關閉操做。
若是關閉KeepAlive,若是仍是每秒50個用戶訪問,若是用戶每次連續的請求數爲3個,那麼 Apache 的總進程數就是 50 * 3= 150 個,若是仍是每一個進程佔用 4M 內存,那麼總的內存消耗爲 600M,這種配置能節省大量內存,可是,系統處理了 150 次 TCP的握手和關閉的操做,所以又會多消耗一些 CPU 資源。
再看看實踐的觀察。
我在一組大量處理動態網頁內容的服務器中,起初打開KeepAlive功能,常常觀察到用戶訪問量大時Apache進程數也很是多,系統頻繁使用交換內存,系統不穩定,有時負載會出現較大波動。關閉了KeepAlive功能後,看到明顯的變化是:Apache 的進程數減小了,空閒內存增長了,用於文件系統Cache的內存也增長了,CPU的開銷增長了,可是服務更穩定了,系統負載也比較穩定,不多有負載大範圍波動的狀況,負載有必定程度的下降;變化不明顯的是:訪問量較少的時候,系統平均負載沒有明顯變化。
總結一下:
在內存很是充足的服務器上,無論是否關閉KeepAlive 功能,服務器性能不會有明顯變化;
若是服務器內存較少,或者服務器有很是大量的文件系統訪問時,或者主要處理動態網頁服務,關閉KeepAlive 後能夠節省不少內存,而節省出來的內存用於文件系統Cache,能夠提升文件系統訪問的性能,而且系統會更加穩定。
ü 補充1
關因而否應該關閉 KeepAlive 選項,我以爲能夠基於下面的一個公式來判斷。
在理想的網絡鏈接情況下,系統的Apache 進程數和內存使用能夠用以下公式表達:
HttpdProcessNumber= KeepAliveTimeout * TotalRequestPerSecond / Average(KeepAliveRequests)
HttpdUsedMemory= HttpdProcessNumber * MemoryPerHttpdProcess
換成中文意思:
總Apache進程數 = KeepAliveTimeout * 每秒種HTTP請求數 / 平均KeepAlive請求
Apache佔用內存 = 總Apache進程數 * 平均每進程佔用內存數
須要特別說明的是:
[平均KeepAlive請求] 數,是指每一個用戶鏈接上服務器後,持續發出的 HTTP 請求數。當 KeepAliveTimeout 等 0或者 KeepAlive 關閉時,KeepAliveTimeout 不參與乘的運算從上面的公式看,若是 [每秒用戶請求]多,[KeepAliveTimeout] 的值大,[平均KeepAlive請求] 的值小,都會形成 [Apache進程數] 多和 [內存]多,可是當 [平均KeepAlive請求] 的值越大時,[Apache進程數] 和 [內存] 都是趨向於減小的。
基於上面的公式,咱們就能夠推算出當 平均KeepAlive請求 <= KeepAliveTimeout 時,關閉 KeepAlive 選項是划算的,不然就能夠考慮打開。
ü 補充2
KeepAlive 該參數控制Apache是否容許在一個鏈接中有多個請求,默認打開。但對於大多數論壇類型站點來講,一般設置爲off以關閉該支持。
ü 補充3
若是服務器前跑有應用squid服務,或者其它七層設備,KeepAlive On 設定要開啓持續長鏈接
實際在 前端有squid 的狀況下,KeepAlive 很關鍵。記得On。
Keeyalive不能爲所欲爲設置,而是須要根據實際狀況,咱們來看一個真實的在我工做中發生的搞笑一次事件:
當時我已經離開該項目了,該項目的TeamLeader看到了keepalive的概念,他只看到了關閉keeyalive能夠節省web服務器的內存,當時咱們的web服務器只有4gb內存,而併發請求的量很大,所以他就把這個keepalive設成了off。
而後直接致使脫機客戶端(脫機客戶端用的是.net而後webservice鏈接)的「login」每次都顯示「出錯」。
一查代碼才知道,因爲這個脫機客戶端使用的是webservice訪問,.net開發團隊在login功能中設了一個超時,30秒,30秒timeout後就認爲服務器沒有開啓,結果呢因爲原來的apache設的是keeyalive和timeout 15秒,如今被改爲了off,好傢伙,根本就沒有了這個timeout概念,所以每次.net登陸直接被apache彈回來,由於沒有了這個timeout的接口了。
因而可知,學東西。。。不能只知其一;不知其二,務必求全面瞭解哈。
儘可能較少DNS查詢的次數。若是你使用了任何」Allow fromdomain」或」Denyfrom domain」指令(也就是domain使用的是主機名而不是IP地址),則代價是要進行兩次DNS查詢(一次正向和一次反向,以確認沒有做假)。因此,爲了獲得最高的性能,應該避免使用這些指令(不用域名而用IP地址也是能夠的)。