轉自:http://blog.51cto.com/ijeremy/1050047
前言
盡管Apache具有重量級、耗資源、低性能(相比其它的WebServer)的特點,但是同時它也具有兼容性強、穩定性高、模塊豐富等特點,且處理動態請求比大多Web Server要優越。另外,它對Windows的支持要比Nginx與Lighttpd要好。
在選擇Web服務器時,我們最經常關注的一點是性能(注1),以下附上一個簡單的性能測試結果:
測試服務器的配置:
Virtualization: OpenVZ RAM: 512MB CPU: 4 cores @ 2.8Ghz OS: CentOS 5
分別安裝了Nginx、Cherokee、Lighttpd和Apache,然后使用並發工具測試,得到如下的結果:
(圖片順序為Nginx、Cherokee、Lighttpd、Apache1、Apache2)
clip_image004clip_image006clip_image008clip_image010clip_image012
結果顯示Apache的性能並是最好的,但即使如此,由於它對windows的支持以及豐富的模塊,還有它於Web領域具有霸主地位。所以我們會經常接觸它,本文就總結自己實際應用到的一些場景。
Apache安裝
下載地址http://httpd.apache.org/download.cgi
clip_image014
值得注意的是2.0.64以后的版本,官網中只提供源碼和netware壓縮包,而之前的版本提供msi文件。由於目標環境為windows,為了簡單起見,本文選擇2.0.64。另,因為安裝都是“next”,所以不再截圖。
Web服務器
一個典型的配置如下
Alias /url "you/local/path"
<Directory "you/local/path">
Options Indexes FollowSymLinks –ExecCGI
DirectoryIndex index.html home/index.php home/index.html
Order allow,deny
Allow from all
Deny from google.com
</Directory>
說明如下
Alias /url "you/local/path":資源訪問的路徑。
Directory "you/local/path":暴露的本地資源之路徑。
Options Indexes FollowSymLinks –ExecCGI:允許列出目錄的內容;允許目錄的符號鏈;不允許執行CGI腳本。
DirectoryIndex index.php index.html home/index.php home/index.html:默認首頁
Order allow,deny:后者優先級大於前者,這一點在后面解釋。
Allow from all:允許來自任何地方的HTTP訪問請求。
Deny from google.com :禁止域名為google.com的HTTP訪問請求。 還記得前面的Order嗎?Deny優先級優於Allow,故Allow指令雖然聲明允許所有的訪問請求,但是apache仍然禁止來自google.com的請求。
反向代理負載均衡服務器
反向代理是指,以代理服務器來接受來自Internet上某個客戶端的連接請求,然后將該請求轉發至內部網絡上的目標服務器,並將從目標服務器上得到的結果返回給客戶端的過程。
clip_image002
反向代理示意圖
反向代理的使用場景主要以下幾個:
1. 加密和SSL加速
2. 負載均衡
3. 緩存靜態內容
4. 壓縮頁面
5. 減速上傳
6. 安全
7. 外網發布
基於反向代理的負載均衡常用的場景為實現動靜態分離。
使用Apache+Tomcat+緩存服務器來實現動靜態分離的方式有三種:JK、http_proxy、ajp_proxy。其中,JK相對后兩者來說配置相對復雜,但是性能較好。JK方式是我們常用的方式。
下面的就是JK一個典型的例子。
JK方式需要額外下載mod_jk模塊,地址為
http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/windows/。下載完成后將其中的mod_jk.so文件拷貝至%APACHE_HOME%/modules目錄下。
JK的配置最關鍵的有三個文件:
文件名
說明
http.conf 前面提到的,Apache服務器的配置文件,這里用來加載JK模塊以及JK配置文件信息。
workers.properties 到Tomcat服務器的鏈接定義文件。
uriworkermap.properties URI映射文件,用來指定哪些URI由Tomcat處理,也可以直接在httpd.conf中配置,但是將這些配置文件單獨放置有一個好處就是JK模塊會定期更新該文件的內容,使得我們修改配置的時候無需重啟Apache服務器。
下面是一個典型的httpd.conf對JK的配置
# (httpd.conf)
# 加載 mod_jk 模塊
LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/workers.properties
JkMountFile conf/uriworkermap.properties
JkLogFile logs/mod_jk.log
JkLogLevel warn
接下來需要在conf目錄創建兩個文件分別是workers.properties、uriworkermap.properties。
內容大概如下
#
# workers.properties
#
# list the workers by name
worker.list=DLOG4J, status
# localhost server 1
# ------------------------
worker.s1.port=8009
worker.s1.host=localhost
worker.s1.type=ajp13
# localhost server 2
# ------------------------
worker.s2.port=8109
worker.s2.host=localhost
worker.s2.type=ajp13
worker.s2.stopped=1
worker.DLOG4J.type=lb
worker.retries=3
worker.DLOG4J.balanced_workers=s1
worker.DLOG4J.sticky_session=1
worker.status.type=status
這里我們配置了兩個類型為 ajp13 的 worker 分別是 s1 和 s2,它們指向同一台服務器上運行在兩個不同端口 8009 和 8109 的 Tomcat。接着我們配置了一個類型為 lb(也就是負載均衡的意思)的 worker,它的名字是 DLOG4J。需要說明的是lb是邏輯的 worker,職責是管理前面配置的兩個物理連接 s1 和 s2。最后我們還配置了一個類型為 status 的 worker,用來監控 JK 本身。但是有了這三個 worker 還不夠,我們還需要告訴 JK,哪些 worker 是可用的,所以就有 worker.list = DLOG4J, status 這行配置。
/*=DLOG4J
/jkstatus=status
!/*.gif=DLOG4J
!/*.jpg=DLOG4J
!/*.png=DLOG4J
!/*.css=DLOG4J
!/*.js=DLOG4J
!/*.htm=DLOG4J
!/*.html=DLOG4J
配置說明所有的請求都由 DLOG4J 這個 worker 進行處理,除了下面的幾個例外。/jkstatus 請求由 status 這個 worker 處理。另外感嘆號開頭且符合規則的URI 不要由 JK 進行,包含圖片、css 文件、js 文件以及靜態 html 文本文件。
緩存服務器
這里只考慮Apache自帶的cache模塊,關於與Squid或者varnish等整合另外介紹。
httpd.conf配置如下:
LoadModule cache_module modules/mod_cache.so
LoadModule disk_cache_module modules/mod_disk_cache.so
UseCanonicalName On
<IfModule mod_cache.c>
CacheDefaultExpire 3600
CacheMaxExpire 86400
<IfModule mod_disk_cache.c>
CacheEnable disk /
CacheRoot d:/cache
CacheDirLevels 2
CacheDirLength 1
CacheMaxFileSize 1048576
CacheMinFileSize 10
</IfModule>
</IfModule>
配置說明
UseCanonicalName:指令設置為 On 可以使用disk緩存時顯著提高緩存的命中率。
CacheDefaultExpire:設置那些既沒有包含"Expires" 或"Cache-Control"頭,也沒有包含"Last-Modified"頭的緩存對象的默認有效期(按秒計),默認是為86400秒。
CacheMaxExpire: 指定失效周期的最大值;默認值是一天 (86400)。
CacheEnable disk / 使用disk 緩存類型 ,這里為緩存目錄
CacheRoot d:/cache 存放緩存文件的目錄,需保證運行的用戶擁有該目錄的寫入權限。
CacheDirLevels指定了子目錄的層數,
CacheDirLength指定了每級子目錄名的字符數
CacheMaxFileSize 緩存文件的最大值(byte)
CacheMaxFileSize:緩存文件的最小值(byte)。
日志服務
(注2)一個典型的例子:
[Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1] client denied by server configuration: /export/home/live/ap/htdocs/test
第一項是事件發生的日期和時間;第二項是事件的嚴重性, LogLevel指令使只有高於指定嚴重性級別的事件才會被記錄;第三項是產生事件的IP地址;此后是事件本身,在此例中,服務器拒絕了這個客戶的訪問。服務器在記錄被訪問文件時,用的是文件系統路徑,而不是Web路徑。
本文僅介紹日志服務使用的模塊和常用的日志格式。
1. 訪問日志
相關模塊
相關指令
· mod_log_config
· mod_setenvif
· CustomLog
· LogFormat
· SetEnvIf
訪問日志中會記錄服務器所處理的所有請求,其文件名和位置取決於 CustomLog 指令,LogFormat指令可以簡化日志的內容。這里闡述訪問日志的服務器配置。
不同版本的Apache httpd用了不同的模塊和指令來控制對訪問的記錄,包括mod_log_referer, mod_log_agent, 模塊和 TransferLog 指令。現在,CustomLog 指令包含了舊版本中相關指令的所有功能。
2. 日志格式
這是一個典型的記錄格式
LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog logs/access_log common
上述定義了一種特定的日志格式字符串,並給它起了個 別名 叫 common,其中的"%"指示服務器用某種信息替換,其他字符信息則不作替換。引號(")必須加轉義符反斜杠,以避免被解釋為字符串的結束。格式字符串還可以包含特殊控制符,如換行"\n"、制表符"\t"。
CustomLog指令建立新的使用指定日志格式的日志文件,除非其文件名以斜杠開頭,否則其路徑是一個相對於ServerRoot的相對路徑。
上述配置是一個普通的日志格式,被稱為Common Log Format (CLF),它被許多不同的Web服務器所采用,並可以為許多日志分析程序所辯識,它產生的事件記錄有如:
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
記錄的各部分說明如下。
127.0.0.1 (%h)
這是發送請求到服務器的客戶的IP地址。如果 HostnameLookups 設為 On,則服務器會嘗試解析這個IP地址的主機名,但是,並不推薦這樣配置,因為會顯著拖慢服務器,最好是用一個日志后續處理器還判斷主機名,比如 logresolve。如果客戶和服務器之間存在代理,那么記錄中的這個IP地址就是那個代理,而不是客戶面前的那個機器的IP地址。
- (%l)
這是由客戶端 identd 判斷的RFC 1413身份,輸出中的符號 "-" 表示此處信息無效。除非在嚴格控制的內部網絡中,此信息通常並不可靠,不應該被使用。只有在IdentityCheck 設為 On時,Apache才會試圖得到這項信息。
frank (%u)
這是由HTTP認證系統得到的訪問該網頁的客戶名稱,環境變量 REMOTE_USER 會被設為該值並提供給CGI腳本。如果狀態碼是401,表示客戶沒有通過認證,則此值沒有意義。如果網頁沒有設置密碼保護,則此項應該是"-"。
[10/Oct/2000:13:55:36 -0700] (%t)
這是服務器完成對請求的處理時的時間,其格式是:
[day/month/year:hour:minute:second zone]
day = 2*digit
month = 3*letter
year = 4*digit
hour = 2*digit
minute = 2*digit
second = 2*digit
zone = (`+' | `-') 4*digit
可以在格式字符串中使用 %{format}t 改變時間的輸出形式,format與C標准庫中的 strftime(3) 用法相同。
"GET /apache_pb.gif HTTP/1.0" (\"%r\")
引號中是客戶發出的包含了許多有用信息的請求內容。可以看出,該客戶的動作是GET,請求的資源是/apache_pb.gif,使用的協議是HTTP/1.0。另外,還可以記錄其他信息,如:格式字符串 "%m %U%q %H" 會記錄動作、路徑、請求串、協議,結果其輸出會和"%r" 一樣。
200 (%>s)
這個是服務器返回給客戶端的狀態碼。這個信息非常有價值,因為它指示了請求的結果,或者是被成功響應了(以2開頭),或者被轉向了(以3開頭),或者出錯了(以4開頭),或者產生了服務器端錯誤(以5開頭)。完整的狀態碼列表參見HTTP specification (RFC2616 section 10).
2326 (%b)
最后這項是返回給客戶端的不包括響應頭的字節數。如果沒有信息返回,則此項應該是 "-",如果希望記錄為 "0" 的形式,就應該用%B。
偽靜態技術
偽靜態是一種將動態頁面請求偽裝成靜態頁面請求的手段,目的是改善動態頁面對搜索引擎不好友好的缺點。同時也可以解決動態頁面不被瀏覽器緩存的問題,提高系統性能。
一個典型的配置:
#
#httpd.conf 配置rewriter模塊
LoadModule rewrite_module modules/mod_rewrite.so
#
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)/forum-([0-9]+)-([0-9]+)\.html$ $1/forumdisplay.jsp?fid=$2&page=$3
</IfModule>
RewriteEngine 指令打開或關閉運行時的重寫引擎。如果設置為off,則此模塊在運行時不執行任何重寫操作。使用該指令可以使此模塊無效,而無須注釋所有的RewriteRule指令!
RewriteRule指令是重寫引擎的根本。此指令可以多次使用。每個指令定義一個簡單的重寫規則。這些規則的定義順序尤為重要——在運行時,規則是按這個順序逐一生效的。
指令后面的參數均為正則表達式,以下是正則表達式的常見的用法:
文本
. 任意一個單字符
[chars] 字符類: "chars"中的任意一個字符
[^chars] 字符類: 不在"chars"中的字符
text1|text2 選擇: text1 或 text2
[num1 – num2] 數字類:從num1~num2
量詞
? 前面的字符出現 0 或 1 次
* 前面的字符出現 0 或 N 次(N > 0)
+ 前面的字符出現 1 或 N 次(N > 1)
分組
(text) text 組
(常用於設置一個選擇的邊界,或用於生成后引用:
在RewriteRule中可以用 $N 引用第N個分組)
錨
^ 以之開頭
$ 以之結尾
轉義
\c 對給定的字符c進行轉義
(比如對".[]()"進行轉義,等等)
當請求URL符合“^(.*)/forum-([0-9]+)-([0-9]+)\.html$”正則表達式時,RewriteRule將使用后者“$1/forumdisplay.jsp?fid=$2&page=$3”(同樣是正則表達式)代替前者。代替的順序為 “.*”=>“$1”、“ [0-9]”=>“ $2”、“ [0-9]”=>“ $3”。比如/hh/forum-1-2.html的URL將被替換為/hh/forumdisplay.jsp?fid=1&page=2。
更加詳細的配置請參考注3
AB測試工具
ab全稱apache benchmark,為apache server自帶的性能測試工具,具有輕量、強大等特點。
clip_image016
結果說明
ServerSoftware: Apache/2.0.64
//待測試服務器使用之軟件版本
Server Hostname: 127.0.0.1
//服務器名稱
Server Port: 80
//服務器端口
Document Path: /apache_pb.gif
//訪問路徑
Document Length: 2326 bytes
//頁面大小
Concurrency Level: 10
//(ab測試的)使用的並發數
Time taken for tests: 0.374986 seconds
//總花費時間
Complete requests: 100
//完成的總請求數量
Failed requests: 0
//失敗的請求數量
Write errors: 0
//寫入失敗的次數
Total transferred: 257400 bytes
//總的數據傳輸量
HTML transferred: 232600 bytes
//總的HTML內容傳輸量
Requests per second: 266.68 [#/sec] (mean)
//最重要的指標之一,平均每次請求花費的時間
Time per request: 37.499 [ms] (mean)
//最重要的指標之二,平均每秒處理多少個請求
Time per request: 3.750 [ms] (mean, across all concurrent requests)
//與以上的結果差別在於:這個結果是先算每次並發的平均時間t1,
最后再對這些時間求平均值t=(t1…tn)/n。
Transfer rate: 669.36 [Kbytes/sec] received
//平均每秒傳輸的流量,可以幫助排除是否存在網絡流量過大導致響應時間延長的問題
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 15 35 15.9 31 93
Waiting: 15 35 15.9 31 93
Total: 15 35 15.9 31 93
Percentage of the requests served within a certain time (ms)
50% 31
66% 31
75% 46
80% 46
90% 62
95% 78
98% 78
99% 93
100% 93 (longest request)
//所有請求的響應情況,重點關注90%用戶的響應時間。
常用參數說明
-n 所有請求數
-c 單次產生的請求數,執行次數等於n/c
-t 限制所有請求在制定時間內完成。默認沒有時間限制。
-p 表單提交之數據
-T 表單提交使用之Content-type頭信息。
-v 設置顯示信息的等級: - 4或以上顯示頭信息, 3或以上顯示響應代碼(404, 200等), 2或以上顯示警告和其他信息。
-V 顯示版本號並退出。
-w 以HTML格式輸出結果。
-i 執行HEAD請求,與GET請求不同的是,HEAD請求並不會下載頁面至本地。
注釋
注1 測試結果引自文章http://www.whisperdale.net/11-nginx-vs-cherokee-vs-apache-vs-lighttpd.html
注2 Apache日志模塊官網文檔:http://man.chinaunix.net/newsoft/ApacheManual/logs.html
注3 Apache mod_rewriter模塊官方文檔:
http://www.phpchina.com/resource/manual/apache/mod/mod_rewrite.html