Apache HTTP Server2.2 筆記

多處理模塊(MPM)

Apache HTTP 服務器被設計爲一個功能強大,並且靈活的 web 服務器, 可以在很多平臺與環境中工作。不同平臺和不同的環境往往需要不同 的特性,或可能以不同的方式實現相同的特性最有效率。Apache 通過模塊化的設計來適應各種環境。這種設計允許網站管理員通過在 編譯時或運行時,選擇哪些模塊將會加載在服務器中,來選擇服務器特性。Apache 2.0 擴展此模塊化設計到最基本的 web 服務器功能。 它提供了可以選擇的多處理模塊(MPM),此類型的模塊負責基本的對請求的處理和指派,它用來綁定到網絡端口上,接受請求, 以及調度子進程處理請求。
在用戶看來,MPM 很像其它 Apache 模塊。主要是區別是,在任何時間, 必須有一個,而且只有一個 MPM 加載到服務器中。MPM 必須在編譯前夕,配置時指定,然後編譯到服務器程序中。 僅當編譯器知道使用了線程時,它纔有能力優化許多函數。爲了使用指定的 MPM,請在執行 configure 時,使用參數 --with-mpm=NAME。NAME 是指定的 MPM 名稱。編譯完成後,可以使用 ./httpd -l 來確定選擇的 MPM。 此命令會列出編譯到服務器程序中的所有模塊,包括 MPM。Windows NT默認的MPM是mpm_winnt,它使用一個單獨的父進程產生一個單獨的子進程,在這個子進程中輪流產生多個線程來處理請求。


常用指令

ServerRoot

設置了服務器所在的目錄。一般來說它將包含conf/和logs/子目錄。其它配置文件的相對路徑即基於此目錄 (比如Include或LoadModule),修改爲你自己的目錄,如ServerRoot "D:/develop/java/run/httpd-2.2.31-win64"。

DocumentRoot

這個指定設置了httpd提供文件的目錄,除非和Alias指令相匹配,服務器會將URL上的路徑添加到DocumentRoot配置的路徑上以構成指向文檔的路徑。比如說:DocumentRoot /usr/web。於是對http://www.my.host.com/index.html的訪問就會指向/usr/web/index.html 。可以配置爲相對ServerRoot的相對路徑,如
DocumentRoot "htdocs"。

Listen

指示Apache只在指定的IP地址和端口上監聽,如果只指定端口,那麼Apache會在所有本機IP地址上監聽。可以指定多個不同的監聽端口和/或地址端口組合。
使服務器在所有地址上同時接受來自端口80和8000的請求,可以這樣寫:
Listen 8
Listen 8000 
接受來自兩個指定的地址+端口的組合:
Listen 192.170.2.1:80 
Listen 192.170.2.5:8000 
IPv6地址必須用方括號括起來:
Listen [2001:db8::a00:20ff:fea7:ccea]:80 
還可以指定http和https協議,一般來說,不需要指定協議,443端口默認https,其他端口默認http,如果指定特殊的端口如8443端口用於https,那麼就需要指定協議。
如:Listen 192.170.2.1:8443 https

LoadModule

加載目標文件或庫,並將其添加到活動模塊列表。語法是LoadModule module filename,module是源代碼文件中用於拼寫module的外部變量名,filename相對於ServerRoot。例如:LoadModule status_module modules/mod_status.so。

ServerAdmin

服務器返回給客戶端的錯誤信息中包含的管理員郵件地址,例如:ServerAdmin [email protected]

IfModule

IfModule test>...</IfModule>配置段用於封裝根據指定的模塊是否啓用而決定是否生效的指令。在<IfModule>配置段中的指令僅當test爲真的時候才進行處理。如果test爲假,所有其間的指令都將被忽略。<IfModule>段中的test可以爲以下兩種方式之一:module或者!module。在第一種情況下,起始和結束標記之間的指令僅當module被載入後才被執行。此模塊可以爲編譯時靜態鏈接進核心的模塊或是使用LoadModule指令動態載入的模塊。第二種情況則相反,僅當module沒有載入時才進行指令的處理。

Include

這個指令允許在服務器配置文件中加入其它配置文件。可以是絕對路徑也可以是相對於ServerRoot的路徑。例如:Include conf/ssl.conf。

Allow和Deny

Allow指令控制哪些主機可以訪問服務器的該區域,可以根據主機名、IP地址、 IP地址範圍或其他環境變量中捕獲的客戶端請求特性進行控制。Deny和Allow作用相反,配置方法一樣。這個指令的第一個參數總是"from",隨後的參數可以有三種不同形式。
第一種是all,Allow from all,允許所有主機訪問。
第二種是允許特定的一臺或多臺主機訪問,有很多的配置方式,常見的如下:
Allow from .net example.edu:主機名與給定字符串匹配或者以給定字符串結尾的主機允許訪問。
Allow from 192.168.1.104 192.168.1.205:允許擁有這些IP地址的主機進行訪問。
Allow from 10.1 192.168.2 :IP地址的開始1到3個字節,用於子網限制。
第三種是允許對服務器的訪問由環境變量的一個擴展指定。指定"Allow from env=env-variable"時,如果環境變量env-variable存在則訪問被允許。使用由mod_setenvif提供的指令SetEnvIf ,服務器用一種基於客戶端請求的彈性方式提供了設置環境變量的能力。因此,這條指令可以用於允許基於像User-Agent(瀏覽器類型)、Referer或其他HTTP請求頭字段的訪問。
SetEnvIf User-Agent ^KnockKnock/2\.0 let_me_in
<Directory /docroot>
Order Deny,Allow
Deny from all
Allow from env=let_me_in
</Directory> 
這種情況下,發送以KnockKnock/2.0開頭的用戶代理標示的瀏覽器將被允許訪問,而所有其他瀏覽器將被禁止訪問。

Order

Order指令控制默認的訪問狀態與Allow和Deny指令生效的順序。
Deny,Allow :Deny指令在Allow指令之前被評估。默認允許所有訪問。任何不匹配Deny指令或者匹配Allow指令的客戶都被允許訪問。 
Allow,Deny :Allow指令在Deny指令之前被評估。默認拒絕所有訪問。任何不匹配Allow指令或者匹配Deny指令的客戶都將被禁止訪問。
規則是先判斷默認的,再根據順序判斷Allow和Deny,最後疊加。
例如下面的例子表示,默認允許所有訪問,然後拒絕192.168.1.109訪問,最後疊加的結果是除了192.168.1.109其他都可以訪問。
Order deny,allow
Deny from 192.168.1.109
下面的例子最後一句是沒有意義的,因爲默認已經決絕了所有的訪問,疊加後還是決絕所有的訪問。
Order allow,deny
Deny from 192.168.1.109


Directory和DirectoryMatch

用於封裝一組指令,使之僅對某個目錄及其子目錄生效。任何可以在"directory"作用域中使用的指令都可以使用。Directory-path可以是一個目錄的完整路徑,或是包含了Unix shell匹配語法的通配符字符串。在通配符字符串中,"*"匹配任何字符串,"?"匹配任何單個的字符,"[seq]"匹配seq序列中的任何字符,符號"/"不被任何通配符所匹配,必須顯式地使用。所以<Directory /*/public_html>將無法匹配/home/user/public_html ,但<Directory /home/*/public_html>能夠正確匹配。例如:<Directory /usr/local/httpd/htdocs>。Directory加上~符號後,可以用正則表達式,例如:<Directory ~ "^/www/(.+/)*[0-9]{3}">。
DirectoryMatch和Directory功能一樣,區別是DirectoryMatch僅支持正則表達式,例如:<DirectoryMatch "^/www/(.+/)*[0-9]{3}">。

Files和FilesMatch

指令提供了基於文件名的訪問控制,與<Directory>指令類似。<Files>能嵌入到<Directory>段中以限制它們作用的文件系統範圍。參數應當是一個文件名或是一個包含了Unix shell匹配語法的通配符字符串。在"~"字符之後同樣可以使用正則表達式。比如:<Files ~ "\.(gif|jpe?g|png)$">,將匹配絕大部分常見的因特網圖象格式。
Files 和FilesMatch功能一樣,區別是FilesMatch僅支持正則表達式,例如:<FilesMatch "\.(gif|jpe?g|png)$">。

Location和LocationMatch

提供了基於URL的訪問控制。與<Directory>指令類似。何時使用<Location>?使用<Location>來將指令應用於獨立於文件系統之外的內容。文件系統之內的內容請使用<Directory>和<Files>指令。不過一個例外是<Location /> ,它可以方便的作用於所有URL。對所有的原始(非代理)請求來說,匹配的URL應該是具有"/path/"形式的URL路徑。不包括訪問方法、主機名、端口或查詢字符串等。對於代理的請求,匹配的URL必須爲"scheme://servername/path"的形式,而且必須包括前綴。URL可以是一個包含了Unix shell匹配語法的通配符字符串。也可以附加"~"字符來表示使用正則表達式。例如:<Location ~ "/(extra|special)/data">
Location和LocationMatch功能一樣,區別是LocationMatch僅支持正則表達式,例如:<LocationMatch "/(extra|special)/data">。

Proxy和ProxyMatch

位於<Proxy>配置段中的指令僅作用於通過mod_proxy代理服務器訪問的、與指定URL匹配的站點。語句中可以是包含了Unix shell匹配語法的通配符字符串。Proxy和ProxyMatch作用一樣,只是ProxyMatch使用正則表達式匹配代理內容。
下例僅允許yournetwork.example.com中的主機通過您的代理服務器訪問代理內容:
<Proxy *>
Order Deny,Allow
Deny from all
Allow from yournetwork.example.com
</Proxy> 
下例中的配置會拒絕通過代理服務器訪問cnn.com站點。
<Proxy http://cnn.com/*>
Order allow,deny
Deny from all
</Proxy> 

DirectoryIndex

指令設置了當客戶端請求一個目錄時尋找的資源列表。參數是多個路徑,用空格分開,可以是相對於被請求目錄的路徑,也可以是不在那個目錄下的絕對路徑。服務器將返回最先找到的那一個。若一個也沒有找到,並且那個目錄設置了Indexes選項(參考Options指令),服務器將會自動產生一個那個目錄中的資源列表。例如:DirectoryIndex index.html。上例配置指示對 http://myserver/docs/ 的請求返回 http://myserver/docs/index.html(若存在)。
DirectoryIndex index.html index.txt /cgi-bin/index.pl。這樣的設置將導致在index.html或index.txt都不存在的情況下執行CGI腳本/cgi-bin/index.pl 。

LogFormat

定義訪問日誌的記錄格式,具體格式參考官網文檔,有兩個參數。第一個參數是格式字符串。第二個參數是別名,別名可以省略,省略別名主要用於TransferLog指令。例如:LogFormat "%v %h %l %u %t \"%r\" %>s %b" common。common是別名。

CustomLog

指令用來記錄對服務器的訪問,有三個參數。第一個參數可以是文件位置(相對於ServerRoot或者絕對路徑),也可以是管道符“|”,後面緊跟着一個把日誌輸出當作標準輸入的處理程序相對於ServerRoot路徑。第二個參數是格式,可以是LogFormat定義的別名,也可以是格式字符串。第三個參數是可選的,它根據服務器上特定的環境變量是否被設置來決定是否對某一特定的請求進行日誌記錄。如果這個特定的環境變量被設置(或者在"env=!name"的情況下未被設置),那麼這個請求將被記錄。
例如:CustomLog "|bin/rotatelogs.exe -l  E:/logs/apache/access_log_%Y_%m_%d.log 1G" combined env=!dontlog

ErrorLog

指令指定了當服務器遇到錯誤時記錄錯誤日誌的文件。可以是絕對路徑也可以是相對於ServerRoot。只有一個參數,可以是文件位置也可以是管道符“|”,後面緊跟着一個把日誌輸出當作標準輸入的處理程序相對於ServerRoot路徑。
例如:ErrorLog "|bin/rotatelogs.exe -l E:/logs/apache/error_log_%Y_%m_%d.log 1G"

配置段合併

合併的結果是後面生效的會覆蓋前面生效的,順序是:
1、<Directory>(除了正則表達式)和.htaccess同時處理;(如果允許的話,.htaccess的設置會覆蓋<Directory>的設置) 
2、<DirectoryMatch>(和<Directory ~>) 
3、<Files>和<FilesMatch>同時處理 
4、<Location>和<LocationMatch>同時處理 
除了<Directory>,每個組都按它們在配置文件中出現的順序被依次處理,而<Directory>會按字典順序由短到長被依次處理,因爲Directory作用於當前目錄及其子目錄。
例如:<Directory /var/web/dir>會先於<Directory /var/web/dir/subdir>被處理。如果有多個指向同一個目錄的<Directory>段,則按它們在配置文件中的順序被依次處理。
用Include指令包含進來的配置被視爲按原樣插入到Include指令的位置。
位於<VirtualHost>容器中的配置段在外部對應的段處理完畢以後再處理,這樣就允許虛擬主機覆蓋主服務器的設置。
當請求是由mod_proxy處理的時候,<Proxy>容器將會在處理順序中取代<Directory>容器的位置。
後面的段覆蓋前面的相應的段的配置。


 A > B > C > D >E 的順序依次生效。
<Location />
E
</Location>
<Files f.html>
D
</Files>
<VirtualHost *>
<Directory /a/b>
B
</Directory>
</VirtualHost>
<DirectoryMatch "^.*b$">
C
</DirectoryMatch>
<Directory /a/b>
A
</Directory>


在下面這個更具體的例子中,無論在<Directory>段中加了多少訪問限制,由於<Location>段將會被最後處理,從而會允許不加限制的對服務器的訪問,可見合併的順序是很重要的,千萬小心!
<Location />
Order deny,allow
Allow from all
</Location>
# 這個<Directory>段將不會實際生效
<Directory />
Order allow,deny
Allow from all
Deny from badguy.example.com

</Directory> 


HTTPS雙向認證配置

生成所需證書


創建CA私鑰
openssl genrsa -aes256 -out private/ca.key.pem 2048
創建CA簽名請求
openssl req -new -key private/ca.key.pem -out private/ca.csr
自己簽發CA根證書
openssl x509 -req -days 3650 -sha1 -extensions v3_ca -signkey private/ca.key.pem -in private/ca.csr -out certificates/ca.cer

創建服務端私鑰 
openssl genrsa -aes256 -out private/server.key.pem 2048
解密服務端私鑰(win32下需要)
rsa -in private/server.key.pem -out private/server.key
創建服務端證書籤發請求 
openssl req -new -key private/server.key.pem -out private/server.csr
利用CA根證書,簽發服務端證書
openssl x509 -req -days 3650 -sha1 -extensions v3_req -CA certificates/ca.cer -CAkey private/ca.key.pem -CAserial ca.srl -CAcreateserial -in private/server.csr -out certificates/server.cer

創建客戶端私鑰
openssl genrsa -aes256 -out private/client.key.pem 2048
創建客戶端證書籤發請求
openssl req -new -key private/client.key.pem -out private/client.csr
利用CA根證書,簽發客戶端證書 
openssl x509 -req -days 3650 -sha1 -extensions v3_req -CA certificates/ca.cer -CAkey private/ca.key.pem -CAserial ca.srl -CAcreateserial -in private/client.csr -out certificates/client.cer
把客戶端證書轉換成p12格式
openssl pkcs12 -export -clcerts -inkey private/client.key.pem -in certificates/client.cer -out certificates/client.p12

配置示例

加載模塊:LoadModule ssl_module modules/mod_ssl.so
#在給定的文件擴展名與特定的內容類型之間建立映射
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl

#允許客戶端使用哪些加密算法套件
SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4

#允許除了SSLv2和SSLv3以外的其他SSL/TLS協議
SSLProtocol all -SSLv2 -SSLv3
SSLProxyProtocol all -SSLv2 -SSLv3

#優先使用服務器端的加密算法套件優先級順序
SSLHonorCipherOrder on

#Apache在啓動時獲取用於解密私鑰文件密語的方式,在win32下無效,所以win32私鑰不能加密
#SSLPassPhraseDialog  builtin

#指定SSL會話緩存的類型,減少握手過程
SSLSessionCache        "shmcb:D:/develop/java/run/httpd-2.2.31-win64/logs/ssl_scache(512000)"
#指定SSL會話緩存有效期,單位秒
SSLSessionCacheTimeout  300

#這個指令指定了SSL引擎使用什麼樣的信號量(互斥鎖)來在多個Apache服務器進程之間實現串行化互斥操作
SSLMutex default

Listen 9001
NameVirtualHost *:9001
<VirtualHost *:9001>
	SSLEngine on
	#服務器證書文件(PEM編碼的X.509證書)
	SSLCertificateFile "conf/test/server.cer"
	#服務器私鑰文件(PEM編碼)
  SSLCertificateKeyFile "conf/test/server.key.new.pem"
	
	#客戶端證書的驗證級別
  SSLVerifyClient require
  #驗證客戶端證書有效性時允許的最大證書鏈深度
	SSLVerifyDepth 1
	#用於客戶端認證的多合一CA證書(PEM格式),此CA簽發的客戶端纔可以訪問
	SSLCACertificateFile "conf/test/ca.cer" 

	
	DocumentRoot D:/develop/java/run/apache-tomcat-8.5.6/webapps/docs
	ServerName www.gjb.com
 	ErrorLog "|bin/rotatelogs.exe -l D:/develop/java/run/httpd-2.2.31-win64/logs/test/9001_error_log_%Y_%m_%d.log 86400"
  CustomLog "|bin/rotatelogs.exe -l  D:/develop/java/run/httpd-2.2.31-win64/logs/test/9001_access_log_%Y_%m_%d.log 86400" combined

	<Directory />
            AllowOverride None
            Order Deny,Allow
        </Directory>
</VirtualHost>

負載均衡

所用Tomcat版本爲8.5.6。

加載以下模塊

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_http_module modules/mod_proxy_http.so


負載均衡策略

輪詢:將根據請求數,按順序輪流地分配到後端服務器上,它均衡地對待後端的每一臺服務器,而不關心服務器實際的連接數和當前的系統負載。

ProxyPass / balancer://mycluster lbmethod=byrequests
<Proxy balancer://mycluster>
BalancerMember ajp://1.2.3.4:8009
BalancerMember ajp://1.2.3.5:8009
</Proxy>

加權輪詢:在輪詢的基礎上加了權重,權重高的多處理,權重低的少處理,權重因子loadfactor可以設置爲1-100,這裏可以設置lbmethod爲bytraffic,意思是根據流量的權重分配,默認lbmethod是byrequests,即根據請求數的權重分配。

ProxyPass / balancer://mycluster lbmethod=byrequests
<Proxy balancer://mycluster>
BalancerMember ajp://1.2.3.4:8009 loadfactor=1
BalancerMember ajp://1.2.3.5:8009 loadfactor=2
</Proxy>


會話管理

stickysession:會話和某個Tomcat綁定,如果這個Tomcat宕機,那麼會話就失效。
首先找到每個Tomcat的server.xml文件,在其中的Engine標籤中加上jvmRoute屬性。

<Engine name="Catalina" defaultHost="localhost" jvmRoute="a">
<Engine name="Catalina" defaultHost="localhost" jvmRoute="b">


接着配置Apache,stickysession=JSESSIONID|jsessionid表示的是後端服務器的session的cookie的key。JSESSIONID和jsessionid分別支持ajp和http。注意BalancerMember指令最後的route=a,這個要和jvmRoute屬性值對應。原理是,Apache響應給客戶端的cookie值後面會加上route的值,以此來記錄cookie屬於哪個Tomcat。nofailover是值有on和off,on表示當綁定的後端服務器錯誤時session中斷,off則不會中斷而是重新分配到其他後端服務器,在後端服務器不支持session複製的時候,最好設置爲on。
#反向代理,balancer://mycluster要和Proxy指令的參數一致
ProxyPass /ice-web1 balancer://mycluster stickysession=JSESSIONID|jsessionid nofailover=off
#此指令使Apache調整HTTP重定向應答中Location, Content-Location, URI頭裏的URL。這樣可以避免在Apache作爲反向代理使用時,後端服務器的HTTP重定向造成的繞過反向代理的問題。
ProxyPassReverse /ice-web1 balancer://mycluster
<Proxy balancer://mycluster>
	BalancerMember ajp://127.0.0.1:8009/ice-web1  route=a
	BalancerMember ajp://127.0.0.1:8010/ice-web1  route=b
</Proxy>


session複製:在Tomcat間共享session,這個方案會消耗更多內存和帶寬,tomcat官方推薦在集羣比較小時採用此方案。
tomcat集羣用的是組播技術,主要需要注意的配置是Membership和Receiver。Membership是組播組,Receiver是接收方。228.0.0.4是組播地址,這是一個保留地址,port是端口。同一個集羣下的機器要加入相同的組播組,所以同一個集羣下的tomcat的Membership是一樣的。Receiver是接收組播信息的配置,如果兩個tomcat在同一個機器,Receiver的port要不相同。如果在不同的機器Receiver的address最好改成ip,如果使用auto,他的值很可能是127.0.0.1,這樣會導致接收不到消息。另外,要將Membership和Receiver的端口加入到防火牆中,不然也會無法訪問。在每個Tomcat的Engine標籤中配置如下:

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
         channelSendOptions="8">


    <Manager className="org.apache.catalina.ha.session.DeltaManager"
             expireSessionsOnShutdown="false"
             notifyListenersOnReplication="true"/>


    <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        <Membership className="org.apache.catalina.tribes.membership.McastService"
                    address="228.0.0.4"
                    port="45564"
                    frequency="500"
                    dropTime="3000"/>
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                  address="auto"
                  port="4000"
                  autoBind="100"
                  selectorTimeout="5000"
                  maxThreads="6"/>


        <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
            <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
        </Sender>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
    </Channel>


    <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
           filter=""/>
    <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>


    <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
              tempDir="/tmp/war-temp/"
              deployDir="/tmp/war-deploy/"
              watchDir="/tmp/war-listen/"
              watchEnabled="false"/>
    <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>


服務器監控

加載模塊
LoadModule info_module modules/mod_info.so
LoadModule status_module modules/mod_status.so


配置

ExtendedStatus On
<Location /server-status> 
	SetHandler server-status
	Order Allow,Deny
	Allow from 127.0.0.1
</Location>

<Location /server-info>
	SetHandler server-info
	Order Allow,Deny
	Allow from 127.0.0.1
</Location>

<Location /balancer-manager>
	SetHandler balancer-manager
	Order Allow,Deny
	Allow from 127.0.0.1
</Location>

假如監聽端口是9000,那麼訪問地址是:http://127.0.0.1:9000/server-status。有個地方要注意的,balancer-manager表示負載均衡監控,如果負載均衡配置在虛擬主機裏,那麼訪問這個監控網頁需要輸入的是虛擬主機的主機名和端口。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章