Apache的安裝部署及工作模式詳解

在LInux服務器上實現web服務,常見無非也就是Apache、Nginx、Tomcat。

三者之間的區別:

  • Apache:支持的模塊比較多,採用servlet處理模型,同步阻塞模型,工作模式多變,對於高併發的場景處理速度比較慢,運行穩定;
  • Nginx :輕量級web服務器,自身支持模塊少,需要藉助第三方模塊支持(Nginx官網就可以下載),採用epoll處理模式,異步非阻塞型,適合高併發場景,配置簡單;
  • Tomcat:apache軟件基金會下開源的子項目,也成爲容器,主要處理java語言編寫的頁面,也可以處理html頁面,併發連接小;

今天這篇博文主要就是圍繞apache-2.4.23版本展開的:

對apache不太瞭解的朋友可以參考博文:基於Apache搭建Web服務器詳解
這裏就不具體介紹apache究竟是什麼、它的起因什麼的了。

博文大綱:
一、httpd-2.4.23版本特性
二、編譯安裝httpd-2.4.23
三、apche的三種工作模式
四、進程與線程的區別

一、httpd-2.4.23版本特性

新版本的httpd-2.4.23新增模塊:

  • mod_proxy_fcgi(可提供fcgi代理);
  • mod_ratelimit(限制用戶帶寬);
  • mod_request(請求模塊,對請求進行過濾);
  • mod_remoteip(匹配客戶端的IP地址);

對於基於IP的訪問控制進行了修改,不再支持allow、deny、order機制,而是統一使用require進行!

新增的特性有:

  • MPM支持在運行時裝載;
  • 支持envet工作模式;
  • 支持異步讀寫功能;
  • 每個模塊都可以指定輸出的日誌級別;
  • 增強版的表達式分析器;
  • 請求配置:<if>,<elseif>;
  • 毫秒級別的keepalive timeout;
  • 支持FQDN的虛擬主機;
  • 支持自定義變量;

接下來開始安裝!

二、編譯安裝httpd-2.4.23

安裝環境:

(1)首先檢查是否安裝httpd軟件包

[root@localhost ~]# rpm -q httpd
未安裝軟件包 httpd 
//如果存在,使用“-e”選項進行卸載

(2)安裝apr

apr是Apache可移植運行庫,是一個對操作系統條用的抽象庫,用於實現Apache內部組件對操作系統的使用,提高系統的可移植性。

[root@localhost ~]# tar zxf apr-1.5.2.tar.gz -C /usr/src
[root@localhost ~]# cd /usr/src/apr-1.5.2/
[root@localhost apr-1.5.2]# ./configure --prefix=/usr/local/apr && make && make install

(3)安裝apr-util

 [root@localhost ~]# tar zxf apr-util-1.5.4.tar.gz -C /usr/src
 [root@localhost ~]# cd /usr/src/apr-util-1.5.4/
 [root@localhost apr-util-1.5.4]#  ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr && make && make install

(4)安裝zlib

[root@localhost ~]# tar zxf zlib-1.2.8.tar.gz -C /usr/src
[root@localhost ~]# cd /usr/src/zlib-1.2.8/
[root@localhost zlib-1.2.8]#  ./configure --prefix=/usr/local/zlib && make && make install

(5)安裝pcre

[root@localhost ~]# tar zxf pcre-8.39.tar.gz -C /usr/src
[root@localhost ~]# cd /usr/src/pcre-8.39/
[root@localhost pcre-8.39]#  ./configure -- prefix=/usr/local/pcre && make && make install

(6)安裝openssl

安裝apache-2.4.23版本時,會提示openssl自帶的版本過低,需要自行手動安裝新的版本。

[root@localhost ~]# tar zxf openssl-1.0.1u.tar.gz -C /usr/src
cd [root@localhost ~]# cd /usr/src/openssl-1.0.1u/
[root@localhost openssl-1.0.1u]#  ./config -fPIC --prefix=/usr/local/openssl enable-shared && make && make install
//PIC使.so文件的代碼段變爲真正意義上的共享
//如果不加-fPIC,則加載.so文件的代碼段時,代碼段引用的數據對象需要重定位, 重定位會修改代碼段的內容,這就造成每個使用這個.so文件代碼段的進程在內核裏都會生成這個.so文件代碼段的copy.每個copy都不一樣,取決於 這個.so文件代碼段和數據段內存映射的位置.

(7)安裝 httpd-2.4.23

[root@localhost ~]# tar zxf httpd-2.4.23.tar.gz -C /usr/src
[root@localhost ~]# cd /usr/src/httpd-2.4.23/
[root@localhost httpd-2.4.23]#  ./configure --prefix=/usr/local/http-2.4.23 --enable-so --enable-cgi \
 --enable-cgid --enable-ssl --with-ssl=/usr/local/openssl --enable-rewrite \
 --with-pcre=/usr/local/pcre --with-z=/usr/local/zlib --with-apr=/usr/local/apr \
 --with-apr-util=/usr/local/apr-util --enable-modules=most --enable-mods-shared=most \
 --enable-mpms-shared=all --with-mpm=event --enable-proxy --enable-proxy-fcgi --enable-expires \
 --enable-deflate  && make && make install

各選項含義:

  • --enable-so:支持動態共享模塊;
  • --enable-rewrite:支持url重寫;
  • --enable-ssl:支持ssl;
  • --with-ssl=/usr/local/openssl:指定ssl安裝位置;
  • --enable-cgi:開啓cgi通用網管接口;
  • --enable-cgid:開啓cig通用網管接口管理程序;
  • --enable-modules=most:編譯成二進制是安裝常用模塊;
  • --enable-mpms-shared=all:安裝apache的所有工作模式;
  • --with-mpm=event:指定默認的運行方式
  • --with-pcre=/usr/local/pcre:支持 pcre ;
  • --with-z=/usr/local/zlib:使用 zlib 壓縮庫;
  • --with-apr=/usr/local/apr:指定 apr 的安裝路徑;
  • --with-apr-util=/usr/local/apr-util:指定 apr-util 的安裝路徑;
  • --enable-expires:支持緩存;
  • --enable-deflate:支持壓縮;

(8)優化http程序的執行路徑

[root@localhost httpd-2.4.23]#  ln -s /usr/local/http-2.4.23/bin/* /usr/local/bin/ 

(9)添加爲系統服務

[root@localhost httpd-2.4.23]#  cp /usr/local/http-2.4.23/bin/apachectl /etc/init.d/httpd 
[root@localhost httpd-2.4.23]# vim /etc/init.d/httpd
#!/bin/bash                      //修改
#chkconfig: 35 85 15                   //添加
…………                  //省略以下內容
[root@localhost httpd-2.4.23]#  chkconfig --add httpd 
[root@localhost httpd-2.4.23]# systemctl start httpd
[root@localhost httpd-2.4.23]# netstat -anpt | grep 80
tcp6       0      0 :::80                   :::*                    LISTEN      108903/httpd 
[root@localhost ~]# httpd -M              //可以查看到httpd服務啓動加載的模塊
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using localhost.localdomain. Set the 'ServerName' directive globally to suppress this message
//關於啓動服務時提示以上的信息,可以省略,也可修改其配置文件(/usr/local/http-2.4.23/conf/httpd.conf)文件找到“ServerName ”一行,根據實際情況進行修改
Loaded Modules:
 core_module (static)
 so_module (static)
 http_module (static)
 authn_file_module (shared)
 authn_core_module (shared)
 authz_host_module (shared)
 authz_groupfile_module (shared)
 authz_user_module (shared)
 authz_core_module (shared)
 access_compat_module (shared)
 auth_basic_module (shared)
 reqtimeout_module (shared)
 filter_module (shared)
 mime_module (shared)
 log_config_module (shared)
 env_module (shared)
 headers_module (shared)
 setenvif_module (shared)
 version_module (shared)
 mpm_prefork_module (shared)
 unixd_module (shared)
 status_module (shared)
 autoindex_module (shared)
 dir_module (shared)
 alias_module (shared)

至此apache-2.4.23已經安裝完成。

三、apche的三種工作模式

(1)Prefork模式

其工作方式:當Apache服務啓動後,mpm_prefork模塊會預先創建多個子進程(默認爲5個),每個子進程只有一個線程,當接收到客戶端請求後,mpm_prefork模塊再將請求轉交給子進程進行處理,並且每個子進程同時只能用於單個請求。如果當前的請求數將超過預先創建的子進程數時,mpm_prefork模塊就會創建新的子進程來處理額外的請求。
如圖:
Apache的安裝部署及工作模式詳解
Apache總是試圖保持一些備用或空閒的子進程用於迎接即將到來的請求。這樣客戶端的請求就不需要在接收後等待子進程的產生。

由於在 mpm_prefork 模塊中,每個請求對應一個子進程,因此其佔用的系統資源相對其他 兩種模塊而言較多。不過 mpm_prefork 模塊的優點在於它的每個子進程都會獨立處理對應 的單個請求,這樣,如果其中一個請求出現問題就不會影響到其他請求。Prefork 在效率上 要比 Worker 要高,但是內存使用大得多不擅長處理高併發的場景。

開啓prefork模式的方法:

[root@localhost ~]# vim /usr/local/http-2.4.23/conf/httpd.conf
//編寫httpd的主配置文件,修改一下內容
Include conf/extra/httpd-mpm.conf                     //默認存在刪除“#”號即可
#LoadModule mpm_event_module modules/mod_mpm_event.so
//添加#號
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
//默認存在,刪除#號即可!
#LoadModule mpm_worker_module modules/mod_mpm_worker.so
//這三行便是apache的三種工作模式,可根據實際情況進行切換
[root@localhost ~]# systemctl restart httpd      //重新啓動httpd服務
[root@localhost ~]# systemctl start httpd     //手動再啓動一下
[root@localhost ~]# httpd -V      //查看httpd的工作模式
//找到這一行即可
Server MPM:     prefork                //可以看到現在Apache工作在prefork模式

與prefork模式有關的配置文件如下:

[root@localhost ~]# vim /usr/local/http-2.4.23/conf/extra/httpd-mpm.conf 
//設置prefork模式也就只有這幾個參數,具體含義:
<IfModule mpm_prefork_module>            //這就是prefork工作模式的參數-
    StartServers             5                //apache啓動時默認開啓的子進程數
    MinSpareServers          5                  //最小的閒置子進程數
    MaxSpareServers         10               //最大的閒置子進程數
    MaxRequestWorkers      250        // 設置了允許同時的最大接入請求數量
    MaxConnectionsPerChild   0         //0表示每個子進程處理完數據後進程永不銷燬,設置成非0時,可防止內存泄漏,服務器在負載小時自動減少自己進程數
</IfModule>

關於其配置內容可參考圖片:
Apache的安裝部署及工作模式詳解
//注 1:MaxRequestWorkers 是這些指令中最爲重要的一個,設定的是 Apache 可以同時處理 的請求,是對 Apache 性能影響最大的參數。如果請求總數已達到這個值(可通過 ps -ef|grep http|wc -l 來確認),那麼後面的請求就要排隊,直到某個已處理請求完畢。這就是系統資源 還剩下很多而 HTTP 訪問卻很慢的主要原因。雖然理論上這個值越大,可以處理的請求就越 多,建議將初始值設爲(以 Mb 爲單位的最大物理內存/2),然後根據負載情況進行動態調整。 比如一臺 4G 內存的機器,那麼初始值就是 4000/2=2000
注 2:prefork 控制進程在最初建立“StartServers”個子進程後,爲了滿足 MinSpareServers 設置的需要創建一個進程,等待一秒鐘,繼續創建兩個,再等待一秒鐘,繼續創建四個……如 此按指數級增加創建的進程數,最多達到每秒 32 個,直到滿足 MinSpareServers 設置的值爲止。這種模式 可以不必在請求到來時再產生新的進程,從而減小了系統開銷以增加性能。 MaxSpareServers 設置了最大的空閒進程數,如果空閒進程數大於這個 值,Apache 會自動 kill 掉一些多餘進程。這個值不要設得過大,但如果設的值比 MinSpareServers 小,Apache 會自 動把其調整爲 MinSpareServers+1。如果站點負載較大,可考慮同時加大 MinSpareServers 和 MaxSpareServers。
注 3:ServerLimit 和 MaxClients(MaxRequestWorkers)有什麼區別呢? 是因爲在 apache1 時代,控制最大進程數只有 MaxClients 這個參數,並且這個參數最大值爲 256,並且是寫死了的,試圖設置爲超過 256 是無效的,這是由於 apache1 時代的服務器硬 件限制的。但是 apache2 時代由於服務器硬件的升級,硬件已經不再是限制,所以使用 ServerLimit 這個參數來控制最大進程數,ServerLimit 值>=MaxClient 值纔有效。ServerLimit 要放在 MaxClients 之前,值要不小於 MaxClients

優點:成熟,兼容所有新老模塊。進程之間完全獨立,使得它非常穩定。同時,不需要擔心線程安全的問題。(我們常用的mod_php,PHP的拓展不需要支持線程安全)

缺點:一個進程相對佔用更多的系統資源,消耗更多的內存。而且,它並不擅長處理高併發請求,在這種場景下,它會將請求放進隊列中,一直等到有可用進程,請求才會被處理。

(2)Worker工作模式

Worker 模式(多線程多進程): 和 prefork 模式相比,worker 使用了多進程和多線程的混合模式,worker 模式也同樣會先預派生一些子進程,然後每個子進程創建一些線程,同時包括一個監聽線程,每個請求過來會 被分配到一個線程來服務。線程比起進程會更輕量,因爲線程是通過共享父進程的內存空間, 因此,內存的佔用會減少一些,在高併發的場景下會比 prefork 有更多可用的線程,表現會 更優秀一些;另外,如果一個線程出現了問題也會導致同一進程下的線程出現問題,如果是 多個線程出現問題,也只是影響 Apache 的一部分,而不是全部。由於用到多進程多線程, 需要考慮到線程的安全了,在使用 keep-alive 長連接的時候,某個線程會一直被佔用,即使 中間沒有請求,需要等待到超時纔會被釋放(該問題在 prefork 模式下也存在) 總的來說,prefork 方式速度要稍高於 worker,然而它需要的 cpu 和 memory 資源也稍多於 woker。如圖:
Apache的安裝部署及工作模式詳解

Apache總是試圖維持一個備用(spare)或是空閒的服務線程池。這樣,客戶端無須等待新線程或新進程的建立即可得到處理。在Unix中,爲了能夠綁定80端口,父進程一般都是以root身份啓動,隨後,Apache以較低權限的用戶建立子進程和線程。User和Group指令用於配置Apache子進程的權限。雖然子進程必須對其提供的內容擁有讀權限,但應該儘可能給予他較少的特權。另外,除非使用了suexec(負責處理CGI和SSI程序的請求,確保網頁使用者能以該目錄或程序的用戶ID來執行遠程程序。) ,否則,這些指令配置的權限將被CGI腳本所繼承。

線程比起進程會更輕量,因爲線程通常會共享父進程的內存空間,因此,內存的佔用會減少一些,在高併發的場景下,表現得比 prefork模式好。

有些人會覺得奇怪,那麼這裏爲什麼不直接使用多線程呢?主要是需要考慮穩定性,如果一個線程異常掛了,會導致父進程連同其他正常的子線程都掛了(它們都是同一個進程下的)。多進程+多線程模式中,各個進程之間都是獨立的,如果某個線程出現異常,受影響的只是Apache的一部分服務,而不是整個服務。其他進程仍然可以工作。

有關work模式的配置:

//自行修改httpd主配置文件,切換模式並重啓服務,接下來
[root@localhost ~]# vim /usr/local/http-2.4.23/conf/extra/httpd-mpm.conf 
<IfModule mpm_worker_module>       //這是worker工作模式的參數
    StartServers             3                  //apache啓動時默認開始的子進程數
    MinSpareThreads         75            //最小空閒數量的工作線程-
    MaxSpareThreads        250          //最大空閒數量的工作線程-
    ThreadsPerChild         25              //每個子進程產生的線程數量
    MaxRequestWorkers      400        //每個進程最大接受的請求數量
    MaxConnectionsPerChild   0         //表示永不銷燬
</IfModule>

有關work模式的詳細介紹請參考圖片:
Apache的安裝部署及工作模式詳解
Worker模式下所能同時處理的請求總數是由子進程總數乘以ThreadsPerChild 值決定的,應該大於等於MaxRequestWorkers。如果負載很大,現有的子進程數不能滿足時,控制進程會派生新的子進程。默認最大的子進程總數是16,加大時 也需要顯式聲明ServerLimit(最大值是20000)。需要注意的是,如果顯式聲明瞭ServerLimit,那麼它乘以 ThreadsPerChild的值必須大於等於MaxRequestWorkers,而且MaxRequestWorkers必須是ThreadsPerChild的整數倍,否則 Apache將會自動調節到一個相應值。

優點:佔據更少的內存,高併發下表現更優秀。

缺點:必須考慮線程安全的問題,因爲多個子線程是共享父進程的內存地址的。如果使用keep-alive的長連接方式,也許中間幾乎沒有請求,這時就會發生阻塞,線程被掛起,需要一直等待到超時纔會被釋放。如果過多的線程,被這樣佔據,也會導致在高併發場景下的無服務線程可用。(該問題在prefork模式下,同樣會發生)。

(3)Event MPM

這是Apache最新的工作模式,它和worker模式很像,不同的是在於它解決了keep-alive長連接的時候佔用線程資源被浪費的問題,在event工作模式中,會有一些專門的線程用來管理這些keep-alive類型的線程,當有真實請求過來的時候,將請求傳遞給服務器的線程,執行完畢後,又允許它釋放。這增強了在高併發場景下的請求處理。如圖:
Apache的安裝部署及工作模式詳解

有關Event MPM模式的配置:

//自行修改httpd主配置文件,切換模式並重啓服務,接下來
[root@localhost ~]# vim /usr/local/http-2.4.23/conf/extra/httpd-mpm.conf 
<IfModule mpm_event_module>
    StartServers             3
    MinSpareThreads         75
    MaxSpareThreads        250
    ThreadsPerChild         25
    MaxRequestWorkers      400
    MaxConnectionsPerChild   0                 
</IfModule>
//其各項配置內容與work模式十分相似,這裏就不多說了!

四、進程與線程的區別

線程就是指進程內的一個執行單元,也是進程內的可調度實體。

線程與進程的區別:

  • 地址空間:進程內的一個執行單元;進程至少有一個線程;它們共享進程的地址空間;而進程有自己獨立的地址空間;
  • 資源擁有:進程是資源分配和擁有的單位,同一個進程內的線程共享進程的資源;
  • 線程是處理器調度的基本單位,但進程不是;
  • 二者均可併發執行;

進程和線程都是由操作系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的併發性。
進程和線程的區別在於:
簡而言之,一個程序至少有一個進程,一個進程至少有一個線程。
線程的劃分尺度小於進程,使得多線程程序的併發性高。
另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程
序的運行效率。

———————— 本文至此結束,感謝閱讀 ————————

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