參考:
http://httpd.apache.org/docs/
http://www.cnblogs.com/huangye-dream/p/3550328.html(nginx和apache優缺點對比)
http://www.kegel.com/c10k.html (c10k問題)
http://apr.apache.org/ (apr介紹)
http://httpd.apache.org/docs/2.4/howto/auth.html(認證與授權)
http://blog.csdn.net/flightsmallbird/article/details/72900817 (CGI、服務器內置模塊、FastCGI、php-fpm的區別)
簡介:
httpd是世界上最流行的的web軟件之一。一般人們也把它叫做apache,這是因爲Apache源於NCSAhttpd服務器,NCSA在項目完成後解散了團隊。但是團隊裏的成員對這個軟件卻有了感情,經常對其修修補補。 Apache取自“a patchy server”的讀音,意思是充滿補丁的服務器,後來apache發展成了一個軟件基金會,維持很多開源項目。所以當提到apache的時候一般包含兩個含義: 一個是apache軟件基金會,一個是開源web軟件httpd。
另外一個很流行的web軟件是nginx,nginx能解決“c10k” 問題,配置簡單,高效,但是它的特性沒有apache多,又不如apache穩定,所以一般用nginx作爲前端處理靜態請求,而apache作爲後端,處理一些動態請求,兩者佔據了web市場的大量份額。
安裝:
我們知道一個電源,燈泡,開關組合的電路可以通過控制開關的閉合來控制燈泡的亮和滅,這是最簡單的電路。後來人們可以設計更復雜的電路來控制燈泡的顯示狀態(比如2個開關控制四個燈的狀態,電壓的高低來控制燈泡亮的程度),但是它們都有一個共同點:輸入一樣,輸出也一樣。 人們在長期的實驗中發現了“簡單就是美”的真理。 於是都只用高低電平來控制燈泡的顯示狀態,並不管其亮的程度,也就是隻管亮與否,不管有多亮,並結合到數學中,用0/1來標記兩種狀態,而計算機就是無數個這種簡單的電子電路集成的一種東西。這也是爲什麼計算機只識別二進制的原因,其實可以做成十進制或其他進制,但是其他進制沒有像二進制這樣,容錯率高(比如,要控制有沒有電壓,顯然比控制電壓到某個值要簡單的多得多)。
所以,計算機最直接能識別的就是01代碼。但是01代碼毫無意義,不利於人類的識別記憶。所以人們給固定的01數字串賦予某個意義,抽象出一個層次,使其不同的數字串結合產生對應的計算機輸入,編寫程序讓這些有意義的字符與01代碼自動轉換,也就是彙編語言。這樣人類的工作量就大大降低了,但是匯源語言還是過於底層,所以人們在其之上根據自身需求還繼續抽象出了各種各樣的編程語言,比如c,perl等。 每個層次之間的交流通道叫做api(就相當於我扎你一下,你會疼,但是我可以用針扎,用手戳,用各種各樣的方法。我這些方法就是所謂的封裝,你允許我扎的地方就是所謂的接口,我還可以做個工具給別人,讓別人也可以扎你,我給別人這個工具也是接口)
但是,每個硬件的廠商不一樣,做出來的接口也就不一樣。 httpd把web和底層的接口分開編譯,用apr(apache portable runtime)爲web的編譯提供一模一樣的接口,讓其忽略底層硬件架構的不同,也就是httpd可以在任何平臺上編譯,只要那個平臺裝了apr,所以要裝httpd,必須先裝apr。
wget http://mirror.bit.edu.cn/apache//httpd/httpd-2.4.27.tar.bz2 wget http://mirrors.tuna.tsinghua.edu.cn/apache//apr/apr-1.6.2.tar.gz wget http://mirrors.tuna.tsinghua.edu.cn/apache//apr/apr-util-1.6.0.tar.gz tar xf httpd-2.4.27.tar.bz2 tar xf apr-1.6.2.tar.gz mv apr-1.6.2 /usr/local/src/httpd-2.4.27/srclib/apr (httpd默認會在自己家目錄的srclib/apr下找apr) tar xf apr-util-1.6.0.tar.gz mv apr-util-1.6.0 /usr/local/src/httpd-2.4.27/srclib/apr-util(同apr) cd /usr/local/src/httpd-2.4.27/ ./configure --prefix=/usr/local/httpd --sysconfdir=/etc/httpd/conf --with-included-apr --with-included-apr-util --enable-mpms-shared=all --sysconfdir:表示httpd的配置文件放在哪 --enable-mpms-shared:表示把多處理模塊編譯成動態模塊,如果靜態編譯的話只能默認使用某一個,rpm包中,redhat官方,在/usr/sbin下分別對應編譯生成了httpd(prefork模型),httpd.worker httpd.event) make make install #輸出二進制文件路徑 [root@cqhdtest httpd]#vim /etc/profile.d/httpd.sh export PATH=/usr/local/httpd/bin:$PATH [root@cqhdtest httpd]#. /etc/profile.d/httpd.sh #輸出頭文件和庫文件 [root@cqhdtest httpd]# ln -s /usr/local/httpd/include /usr/include/httpd [root@cqhdtest httpd]# vi /etc/ld.so.conf.d/httpd.conf /usr/local/httpd/lib [root@cqhdtest httpd]# ldconfig -v (生成共享庫緩存) /usr/local/httpd/lib: libaprutil-1.so.0 -> libaprutil-1.so.0.6.0 libapr-1.so.0 -> libapr-1.so.0.6.2
#生成服務腳本(源碼包裏默認有提供,只是需要修改下腳本) cp /usr/local/src/httpd-2.4.27/build/rpm/httpd.init /etc/init.d/httpd chmod +x /etc/init.d/httpd [root@cqhdtest]# vi /etc/sysconfig/httpd HTTPD=/usr/local/httpd/bin/httpd PIDFILE=/usr/local/httpd/logs/httpd.pid #最少必須修改這兩個變量,/etc/sysconfig/httpd其實是/etc/init.d/httpd的配置文件,因爲腳本默認會在/usr/sbin查找httpd可執行程序,所以必須修改這個變量,pidfile也可以不用/etc/sysconfig/httpd設置,直接httpd.conf修改爲默認的pid文件位置。
這裏貼上httpd腳本備用:
#!/bin/bash # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # # httpd Startup script for the Apache Web Server # # chkconfig: - 85 15 # description: The Apache HTTP Server is an efficient and extensible \ # server implementing the current HTTP standards. # processname: httpd # pidfile: /var/run/httpd.pid # config: /etc/sysconfig/httpd # ### BEGIN INIT INFO # Provides: httpd # Required-Start: $local_fs $remote_fs $network $named # Required-Stop: $local_fs $remote_fs $network # Should-Start: distcache # Short-Description: start and stop Apache HTTP Server # Description: The Apache HTTP Server is an extensible server # implementing the current HTTP standards. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions # What were we called? Multiple instances of the same daemon can be # created by creating suitably named symlinks to this startup script prog=$(basename $0 | sed -e 's/^[SK][0-9][0-9]//') if [ -f /etc/sysconfig/${prog} ]; then . /etc/sysconfig/${prog} fi # Start httpd in the C locale by default. HTTPD_LANG=${HTTPD_LANG-"C"} # This will prevent initlog from swallowing up a pass-phrase prompt if # mod_ssl needs a pass-phrase from the user. INITLOG_ARGS="" # Set HTTPD=/usr/sbin/httpd.worker in /etc/sysconfig/httpd to use a server # with the thread-based "worker" MPM; BE WARNED that some modules may not # work correctly with a thread-based MPM; notably PHP will refuse to start. httpd=${HTTPD-/usr/sbin/httpd} pidfile=${PIDFILE-/var/run/${prog}.pid} lockfile=${LOCKFILE-/var/lock/subsys/${prog}} RETVAL=0 # check for 1.3 configuration check13 () { CONFFILE=/etc/httpd/conf/httpd.conf GONE="(ServerType|BindAddress|Port|AddModule|ClearModuleList|" GONE="${GONE}AgentLog|RefererLog|RefererIgnore|FancyIndexing|" GONE="${GONE}AccessConfig|ResourceConfig)" if grep -Eiq "^[[:space:]]*($GONE)" $CONFFILE; then echo echo 1>&2 " Apache 1.3 configuration directives found" echo 1>&2 " please read @docdir@/migration.html" failure "Apache 1.3 config directives test" echo exit 1 fi } # The semantics of these two functions differ from the way apachectl does # things -- attempting to start while running is a failure, and shutdown # when not running is also a failure. So we just do it the way init scripts # are expected to behave here. start() { echo -n $"Starting $prog: " check13 || exit 1 LANG=$HTTPD_LANG daemon --pidfile=${pidfile} $httpd $OPTIONS RETVAL=$? echo [ $RETVAL = 0 ] && touch ${lockfile} return $RETVAL } stop() { echo -n $"Stopping $prog: " killproc -p ${pidfile} -d 10 $httpd RETVAL=$? echo [ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile} } reload() { echo -n $"Reloading $prog: " check13 || exit 1 killproc -p ${pidfile} $httpd -HUP RETVAL=$? echo } # See how we were called. case "$1" in start) start ;; stop) stop ;; status) if ! test -f ${pidfile}; then echo $prog is stopped RETVAL=3 else status -p ${pidfile} $httpd RETVAL=$? fi ;; restart) stop start ;; condrestart) if test -f ${pidfile} && status -p ${pidfile} $httpd >&/dev/null; then stop start fi ;; reload) reload ;; configtest) LANG=$HTTPD_LANG $httpd $OPTIONS -t RETVAL=$? ;; graceful) echo -n $"Gracefully restarting $prog: " LANG=$HTTPD_LANG $httpd $OPTIONS -k $@ RETVAL=$? echo ;; *) echo $"Usage: $prog {start|stop|restart|condrestart|reload|status|graceful|help|configtest}" exit 1 esac exit $RETVAL
httpd配置文件簡介:
httpd配置文件主要是httpd編譯時設置的家目錄下的conf裏面的httpd.conf
httpd.conf的是由一堆配置指令組成的,它的一個配置片段如下
# DocumentRoot: The directory out of which you will serve your # documents. By default, all requests are taken from this directory, but # symbolic links and aliases may be used to point to other locations. # #DocumentRoot "/usr/local/httpd/htdocs" DocumentRoot "/var/www/html"
以#號+單空格開頭的表示註釋, #後不接空格,表示後面是可用的指令,但是並不啓用(比如上面的#DocumentRoot)所有的指令都可以通過http://httpd.apache.org/docs/2.4/mod/quickreference.html 查看詳細幫助
非#開頭的表示正式啓用的配置。
httpd的虛擬主機簡介:
有時候我們會遇到這種情況:我們需要一個網站,但是這個網站訪問量很小,用一個物理機太浪費,不用又不行。而且如果僅僅需要一兩個這種網站浪費就浪費點也就算了,要是同時擁有多個這種站點,那麼付出的代價就很客觀了。
於是,虛擬主機就應運而生了。所謂虛擬主機,就是一臺物理機同時開多個站點,因爲一個站點對應一臺主機,這個主機並不是真正意義上的主機,所以稱之爲虛擬主機。
一臺物理機開多個站點,這些站點必須要有唯一的標識符來標識它們。一般有以下三種類型:
1.基於端口的虛擬主機
使用相同的ip,以不同的端口來區分各站點
2.基於ip的虛擬主機
監聽不同的ip,根據ip來區分各主機
3.基於域名的虛擬主機
因爲1、2兩種類型要麼沒有那麼多ip,要麼使用其他端口與我們習慣不符,所以催生了這一種類型的虛擬主機。
這種類型的主機基於http協議的host頭部,當數據包進來的時候,進程根據這個頭部來區分各虛擬主機(因爲tcp包的首部都一樣,所以只能在http頭部進行標識區分)
下面是vhost的一個案例:
<VirtualHost *:80> DocumentRoot "/var/www/a" ServerName www.a.com ServerAlias www.aa.com <Directory "/var/www/a"> AllowOverride None Options None Require all granted </Directory> </VirtualHost> <VirtualHost *:80> DocumentRoot "/var/www/b" ServerName www.b.com </VirtualHost>
apache的虛擬主機配置是以<VirtualHost>指令開頭和結尾的,中間可以包含許多指令。
以上述段爲例,DocumentRoot指定了網站的根目錄,SeverName指定了網站的域名。apache的配置遵循“匹配範圍小優先生效原則”,就是說,假設你在全局配置段也配置了DocumentRoot “/tmp/www" ,那麼當訪問www.a.com的時候,進程會去/var/www/a找web文件,當沒匹配到www.a.com或者www.b.com的時候就會到全局配置裏面的/tmp/www裏面找。
這裏www.a.com的virtualhost還加了Directory的原因是爲了和www.b.com對比區分。apache 2.4默認沒有設置對目錄權限的話會禁止訪問,提示403錯。
apache的模塊使用簡介:
apache的一大特點是很多功能都可以通過模塊動態加載,模塊的使用方法也很簡單,使用LoadModule指令加載,再利用IfModule指令配置模塊的使用參數即可
格式:
LoadModule MODULE_NAME MODULE_PATH
<IfModule MODULE_NAME>
指令1 參數
指令2 參數
...
</IfModule>
MODULE_NAME:表示模塊的名稱(應該是可以自定義的,IfModule匹配的時候對應即可,未測試)
MODULE_PATH:模塊所在的路徑,可以使用相對路徑,也可以使用絕對路徑
httpd的認證與授權: http://httpd.apache.org/docs/2.4/howto/auth.html
<Directory "/var/www/a/secret">
AllowOverride None
Options Indexes
AuthType Basic
AuthName "test"
AuthBasicProvider file
AuthUserFile "/usr/local/httpd/passwords"
Require user linzb
</Directory>
options:指明在目錄中允許的動作,indexes表示允許
AuthType:表示認證類型,Basic表示使用mod_auth_basic模塊的實現,類似的還有digest等
AuthName:這個自己記憶用,隨意取,可以不寫
AuthBasicProvider:認證的提供者,有file,dbm等,這裏使用file這種簡潔但是不安全的做法
AuthUserFile:認證文件的位置
Require:授權要求,有user,group等
不難理解,在設置網站用戶認證的時候,要事先用htpasswd -c /usr/local/httpd/passwords linzb 命令生成用戶名和密碼的認證文件
httpd與php的結合:
1.基於模塊的方式:http://php.net/manual/en/install.unix.apache2.php
php的安裝:
wget http://cn2.php.net/distributions/php-7.1.7.tar.bz2
tar xf php-7.1.7.tar.bz2
cd php-7.1.7
./configure --with-apxs2=/usr/local/httpd/bin/apxs && make && make install
cp php.ini-development /usr/local/lib/php.ini
httpd的配置:
vi /etc/httpd/conf/httpd.conf # 增加以下幾行
---------------------------------------------------
LoadModule php7_module modules/libphp7.so
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
----------------------------------------------------
2.基於fastcgi的方式:
這裏使用mod_proxy_fcgi.so, 用mod_fastcgi.so配置起來比較繁瑣
php的安裝:
wget http://cn2.php.net/distributions/php-7.1.7.tar.bz2
tar xf php-7.1.7.tar.bz2
cd php-7.1.7
./configure --with-apxs2=/usr/local/httpd/bin/apxs --enable-fpm && make && make install
cp php.ini-development /usr/local/lib/php.ini
cp sapi/fpm/init.d.php-fpm.in /etc/init.d/php-fpm
chmod +x /etc/init.d/php-fpm
vi /etc/init.d/php-fpm # 修改三個地方
----------------------------------------------
prefix=
php_fpm_BIN=/usr/local/sbin/php-fpm
php_fpm_CONF=/usr/local/etc/php-fpm.conf
php_fpm_PID=/var/run/php-fpm.pid
----------------------------------------------
vi /usr/local/etc/php-fpm.conf
;;;;;;;;;;;;;;;;;;;;; ; FPM Configuration ; ;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;; ; Global Options ; ;;;;;;;;;;;;;;;;;; [global] pid = /var/run/php-fpm.pid error_log = /var/log/php-fpm.log log_level = warning emergency_restart_threshold = 30 emergency_restart_interval = 60s process_control_timeout = 5s daemonize = yes ;;;;;;;;;;;;;;;;;;;; ; Pool Definitions ; ;;;;;;;;;;;;;;;;;;;; [www] listen = 127.0.0.1:9000 listen.backlog = -1 listen.owner = www listen.group = www user = www group = www pm = dynamic pm.max_children = 256 pm.start_servers = 8 pm.min_spare_servers = 8 pm.max_spare_servers = 32 pm.max_requests = 2048 pm.process_idle_timeout = 10s request_terminate_timeout = 120 request_slowlog_timeout = 20 pm.status_path = /php-fpm_status slowlog = log/slow.log rlimit_files = 51200 rlimit_core = 0 catch_workers_output = yes ;env[HOSTNAME] = your_uname env[PATH] = /usr/local/bin:/usr/bin:/bin env[TMP] = /tmp env[TMPDIR] = /tmp env[TEMP] = /tmp
/etc/init.d/php-fpm start
httpd的配置:
vi /etc/httpd/conf/httpd.conf # 增加以下幾行
--------------------------------------------------------
LoadModule proxy_module modules/mod_proxy.so #mod_proxy_fcgi.so依賴於這個模塊
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
<FilesMatch "\.php$">
SetHandler "proxy:fcgi://127.0.0.1:9000"
</FilesMatch>
----------------------------------------------------------
3.基於cgi的方式
不好用,而且操作複雜,這裏不寫,只是提醒自己還有這麼一種
cgi、fastcgi和基於模塊方式的對比:
以我個人看過的文檔和視頻,我的理解是這樣:
使用cgi的時候,當一個動態頁面請求到來的時候,http都要請求操作系統生成一個cgi進程去解釋執行動態腳本,這種方式資源消耗大,執行效率低,所以,後來人們把執行動態腳本的功能做成模塊。模塊的方式,系統消耗變小了,執行效率也比較高,但是這種方式有個缺點,對php配置的修改,要重啓httpd才能生效,而且當執行php出現了問題的時候,httpd進程也隨之受到影響,所以就有了第三種:fastcgi。 fastcgi其實是在cgi的基礎上,多了個進程專門管理cgi解釋器的生成執行銷燬等,以後當有請求進來的時候,httpd直接把請求交給fastcgi管理進程,這樣httpd和php的執行效率都得到了提高,而且故障發生時互不影響,所以一般建議使用fastcgi的方式
具體可以參考:http://blog.csdn.net/flightsmallbird/article/details/72900817
httpd的ssl配置:
vi httpd.conf
---------------------------------
LoadModule ssl_module modules/mod_ssl.so
Include /etc/httpd/conf/extra/ssl.conf
---------------------------------------
[root@cqhdtest extra]# cat ssl.conf
Listen 443
<VirtualHost *:443>
DocumentRoot "/usr/local/httpd/htdocs"
ServerName www.a.com:443
SSLEngine on
SSLCertificateFile "/etc/httpd/conf/httpd.crt"
SSLCertificateKeyFile "/etc/httpd/conf/httpd.key"
</VirtualHost>
參考(個人筆記):http://linzb.blog.51cto.com/5192423/1870944 (CA)