在LInux服務器上實現web服務,常見無非也就是Apache、Nginx、Tomcat。php
三者之間的區別:html
- Apache:支持的模塊比較多,採用servlet處理模型,同步阻塞模型,工做模式多變,對於高併發的場景處理速度比較慢,運行穩定;
- Nginx :輕量級web服務器,自身支持模塊少,須要藉助第三方模塊支持(Nginx官網就能夠下載),採用epoll處理模式,異步非阻塞型,適合高併發場景,配置簡單;
- Tomcat:apache軟件基金會下開源的子項目,也成爲容器,主要處理java語言編寫的頁面,也能夠處理html頁面,併發鏈接小;
今天這篇博文主要就是圍繞apache-2.4.23版本展開的:java
對apache不太瞭解的朋友能夠參考博文:基於Apache搭建Web服務器詳解
這裏就不具體介紹apache到底是什麼、它的原由什麼的了。web
博文大綱:
1、httpd-2.4.23版本特性
2、編譯安裝httpd-2.4.23
3、apche的三種工做模式
4、進程與線程的區別apache
新版本的httpd-2.4.23新增模塊:vim
- mod_proxy_fcgi(可提供fcgi代理);
- mod_ratelimit(限制用戶帶寬);
- mod_request(請求模塊,對請求進行過濾);
- mod_remoteip(匹配客戶端的IP地址);
對於基於IP的訪問控制進行了修改,再也不支持allow、deny、order機制,而是統一使用require進行!centos
新增的特性有:緩存
- MPM支持在運行時裝載;
- 支持envet工做模式;
- 支持異步讀寫功能;
- 每一個模塊均可以指定輸出的日誌級別;
- 加強版的表達式分析器;
- 請求配置:<if>,<elseif>;
- 毫秒級別的keepalive timeout;
- 支持FQDN的虛擬主機;
- 支持自定義變量;
接下來開始安裝!安全
安裝環境:bash
[root@localhost ~]# rpm -q httpd 未安裝軟件包 httpd //若是存在,使用「-e」選項進行卸載
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
[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
[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
[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
安裝apache-2.4.23版本時,會提示openssl自帶的版本太低,須要自行手動安裝新的版本。
[root@localhost ~]# tar zxf openssl-1.0.1u.tar.gz -C /usr/src [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文件代碼段和數據段內存映射的位置.
[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:支持壓縮;
[root@localhost httpd-2.4.23]# ln -s /usr/local/http-2.4.23/bin/* /usr/local/bin/
[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已經安裝完成。
其工做方式:當Apache服務啓動後,mpm_prefork模塊會預先建立多個子進程(默認爲5個),每一個子進程只有一個線程,當接收到客戶端請求後,mpm_prefork模塊再將請求轉交給子進程進行處理,而且每一個子進程同時只能用於單個請求。若是當前的請求數將超過預先建立的子進程數時,mpm_prefork模塊就會建立新的子進程來處理額外的請求。
如圖:
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>
關於其配置內容可參考圖片:
//注 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的拓展不須要支持線程安全)
缺點:一個進程相對佔用更多的系統資源,消耗更多的內存。並且,它並不擅長處理高併發請求,在這種場景下,它會將請求放進隊列中,一直等到有可用進程,請求才會被處理。
Worker 模式(多線程多進程): 和 prefork 模式相比,worker 使用了多進程和多線程的混合模式,worker 模式也一樣會先預派生一些子進程,而後每一個子進程建立一些線程,同時包括一個監聽線程,每一個請求過來會 被分配到一個線程來服務。線程比起進程會更輕量,由於線程是經過共享父進程的內存空間, 所以,內存的佔用會減小一些,在高併發的場景下會比 prefork 有更多可用的線程,表現會 更優秀一些;另外,若是一個線程出現了問題也會致使同一進程下的線程出現問題,若是是 多個線程出現問題,也只是影響 Apache 的一部分,而不是所有。因爲用到多進程多線程, 須要考慮到線程的安全了,在使用 keep-alive 長鏈接的時候,某個線程會一直被佔用,即便 中間沒有請求,須要等待到超時纔會被釋放(該問題在 prefork 模式下也存在) 總的來講,prefork 方式速度要稍高於 worker,然而它須要的 cpu 和 memory 資源也稍多於 woker。如圖:
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模式的詳細介紹請參考圖片:
Worker模式下所能同時處理的請求總數是由子進程總數乘以ThreadsPerChild 值決定的,應該大於等於MaxRequestWorkers。若是負載很大,現有的子進程數不能知足時,控制進程會派生新的子進程。默認最大的子進程總數是16,加大時 也須要顯式聲明ServerLimit(最大值是20000)。須要注意的是,若是顯式聲明瞭ServerLimit,那麼它乘以 ThreadsPerChild的值必須大於等於MaxRequestWorkers,並且MaxRequestWorkers必須是ThreadsPerChild的整數倍,不然 Apache將會自動調節到一個相應值。
優勢:佔據更少的內存,高併發下表現更優秀。
缺點:必須考慮線程安全的問題,由於多個子線程是共享父進程的內存地址的。若是使用keep-alive的長鏈接方式,也許中間幾乎沒有請求,這時就會發生阻塞,線程被掛起,須要一直等待到超時纔會被釋放。若是過多的線程,被這樣佔據,也會致使在高併發場景下的無服務線程可用。(該問題在prefork模式下,一樣會發生)。
這是Apache最新的工做模式,它和worker模式很像,不一樣的是在於它解決了keep-alive長鏈接的時候佔用線程資源被浪費的問題,在event工做模式中,會有一些專門的線程用來管理這些keep-alive類型的線程,當有真實請求過來的時候,將請求傳遞給服務器的線程,執行完畢後,又容許它釋放。這加強了在高併發場景下的請求處理。如圖:
有關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模式十分類似,這裏就很少說了!
線程就是指進程內的一個執行單元,也是進程內的可調度實體。
線程與進程的區別:
- 地址空間:進程內的一個執行單元;進程至少有一個線程;它們共享進程的地址空間;而進程有本身獨立的地址空間;
- 資源擁有:進程是資源分配和擁有的單位,同一個進程內的線程共享進程的資源;
- 線程是處理器調度的基本單位,但進程不是;
- 兩者都可併發執行;
進程和線程都是由操做系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的併發性。
進程和線程的區別在於:
簡而言之,一個程序至少有一個進程,一個進程至少有一個線程。
線程的劃分尺度小於進程,使得多線程程序的併發性高。
另外,進程在執行過程當中擁有獨立的內存單元,而多個線程共享內存,從而極大地提升了程
序的運行效率。
———————— 本文至此結束,感謝閱讀 ————————