26.第20章 HTTP協議和WEB服務器APACHE


一.經典面試題:在瀏覽器地址欄輸入一個 URL 后回車,背后發生了什么?

1.DNS

在瀏覽器中輸入URL后,首先要進行DNS解析,DNS解析的順序為:

  • 瀏覽器緩存
  • 本地hosts文件
  • 系統緩存
  • 路由器緩存
  • DNS服務器迭代查詢

2.發送請求

通過DNS得到目標的IP地址后,通過TCP協議向服務器發送請求即三次握手。

3.服務器永久重定向響應

大多數的網站會將用戶訪問的地址永久重定向,這主要與緩存和搜索排名有關。

  • 搜索排名方面:例如www.test.com與test.com搜索引擎認為是兩個網站,不會將排名合並。如果使用重定向將test.com定向到www.test.com搜索引擎就會認為是一個頁面將排名信息合並。
  • 緩存方面:如果使用不同的地址,在緩存中出現好幾次,緩存友好性變差

4.跟蹤重定向地址

根據返回新重定向地址,重新發送新的http請求

5.處理HTTP請求,返回響應

  • 建立連接:服務器允許客戶端建立連接
  • 接受請求:從網絡中讀取HTTP報文交給Nginx或者Apache進行規則匹配
  • 處理請求:根據方法,資源,首部和可選的主體部分對請求進行處理
  • 訪問資源:尋找存儲對象,訪問報文中指定的資源
  • 構建響應報文:創建有正確首部的HTTP響應報文

6.處理HTTP響應

  • 發送響應:將響應會送給客戶端
  • 記錄日志:將與已經完成的事務記錄在一個日志文件中

7.瀏覽器解析顯示

瀏覽器得到頁面后會進行展示,如果還包含其他外部資源如圖片、視頻等等則繼續請求其他資源。

二.HTTP1.0和HTTP1.1的區別

  • 緩存處理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires來做為緩存判斷的標准,HTTP1.1則引入了更多的緩存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供選擇的緩存頭來控制緩存策略
  • 帶寬優化及網絡連接的使用,HTTP1.0中,存在一些浪費帶寬的現象,例如:客戶端只是需要某個對象的一部分,而服務器卻將整個對象送過來了,並且不支持斷點續傳功能,HTTP1.1則在請求頭引入了range頭域,它允許只請求資源的某個部分,即返回碼是206(Partial Content),方便了開發者自由的選擇以便於充分利用帶寬和連接
  • 錯誤通知的管理,在HTTP1.1中新增24個狀態響應碼,如409(Conflict)表示請求的資源與資源當前狀態沖突;410(Gone)表示服務器上的某個資源被永久性的刪除
  • Host 頭處理,在HTTP1.0中認為每台服務器都綁定一個唯一的IP地址,因此,請求消息中的URL並沒有傳遞主機名(hostname)。但隨着虛擬主機技術的發展,在一台物理服務器上可以存在多個虛擬主機(Multi-homed Web Servers),並且它們共享一個IP地址。HTTP1.1的請求消息和響應消息都應支持Host頭域,且請求消息中如果沒有Host頭域會報告一個錯誤(400 BadRequest)
  • 長連接,HTTP 1.1支持長連接(PersistentConnection)和請求的流水線(Pipelining)處理,在一個TCP連接上可以傳送多個HTTP請求和響應,減少了建立和關閉連接的消耗和延遲,在HTTP1.1中默認開啟Connection: keep-alive,彌補了HTTP1.0每次請求都要創建連接的缺點

HTTP1.0和1.1的問題

  • HTTP1.x在傳輸數據時,每次都需要重新建立連接,無疑增加了大量的延遲時間,特別是在移動端更為突出
  • HTTP1.x在傳輸數據時,所有傳輸的內容都是明文,客戶端和服務器端都無法驗證對方的身份,無法保證數據的安全性
  • HTTP1.x在使用時,header里攜帶的內容過大,增加了傳輸的成本,並且每次請求header基本不怎么變化,尤其在移動端增加用戶流量
  • 雖然HTTP1.x支持了keep-alive,來彌補多次創建連接產生的延遲,但是keep-alive使用多了同樣會給服務端帶來大量的性能壓力,並且對於單個文件被不斷請求的服務(例如圖片存放網站),keep-alive可能會極大的影響性能,因為它在文件被請求之后還保持了不必要的連接很長時間

三.HTTP2.0和SPDY區別:

  • HTTP2.0 支持明文 HTTP 傳輸,而 SPDY 強制使用 HTTPS
  • HTTP2.0 消息頭的壓縮算法采用 HPACK,而非 SPDY 采用的 DEFLATE

四.MPM multi-processing module 工作模式

  • prefork:多進程I/O模型,每個進程響應一個請求,CentOS 7 默認模型
    一個主進程:生成和回收n個子進程,創建套接字,不響應請求
    多個子進程:工作 work進程,每個子進程處理一個請求;系統初始時,預先生成多個空閑進程,等待請求

​ Prefork MPM: 預派生模式,有一個主控制進程,然后生成多個子進程,每個子進程有一個獨立的線程響應用戶請求,相對比較占用內存,但是比較穩定,可以設置最大和最小進程數,是最古老的一種模式,也是最穩定的模式,適用於訪問量不是很大的場景
​ 優點:穩定
​ 缺點:慢,占用資源,不適用於高並發場景

  • worker:復用的多進程I/O模型,多進程多線程,IIS使用此模型
    一個主進程:生成m個子進程,每個子進程負責生個n個線程,每個線程響應一個請求,並發響應
    請求:m*n

​ worker MPM:是一種多進程和多線程混合的模型,有一個控制進程,啟動多個子進程,每個子進程里面包含固定的線程,使用線程程來處理請求,當線程不夠使用的時候會再啟動一個新的子進程,然后在進程里面再啟動線程處理請求,由於其使用了線程處理請求,因此可以承受更高的並發。
​ 優點:相比prefork 占用的內存較少,可以同時處理更多的請求
​ 缺點:使用keep-alive的長連接方式,某個線程會一直被占據,即使沒有傳輸數據,也需要一直等待到超時才會被釋放。如果過多的線程,被這樣占據,也會導致在高並發場景下的無服務線程可用。(該問題在prefork模式下,同樣會發生)

  • event:事件驅動模型(worker模型的變種),CentOS8 默認模型

​ 一個主進程:生成m個子進程,每個子進程負責生個n個線程,每個線程響應一個請求,並發響應
​ 請求:m*n,有專門的監控線程來管理這些keep-alive類型的線程,當有真實請求時,將請求傳遞給服務線程,執行完畢后,又允許釋放。這樣增強了高並發場景下的請求處理能力
​ uevent MPM:Apache中最新的模式,屬於事件驅動模型(epoll),每個進程響應多個請求,在現在版本里的已經是穩定可用的模式。它和worker模式很像,最大的區別在於,它解決了keep-alive場景下,長期被占用的線程的資源浪費問題(某些線程因為被keep-alive,空掛在哪里等待,中間幾乎沒有請求過來,甚至等到超時)。event MPM中,會有一個專門的線程來管理這些keep-alive類型的線程,當有真實請求過來的時候,將請求傳遞給服務線程,執行完畢后,又允許它釋放。這樣增強了高並發場景下的請求處理能力
​ event只在有數據發送的時候才開始建立連接,連接請求才會觸發工作線程,即使用了TCP的一個選項,叫做延遲接受連接TCP_DEFER_ACCEPT,加了這個選項后,若客戶端只進行TCP連接,不發送請求,則不會觸發Accept操作,也就不會觸發工作線程去干活,進行了簡單的防攻擊(TCP連接)
​ 優點:單線程響應多請求,占據更少的內存,高並發下表現更優秀,會有一個專門的線程來管理keep-alive類型的線程,當有真實請求過來的時候,將請求傳遞給服務線程,執行完畢后,又允許它釋放
​ 缺點:沒有線程安全控制
​ httpd-2.4:event 穩定版,centos7 以后默認
​ httpd-2.2:event 測試版,centos6 默認

五.一鍵編譯安裝httpd2.4腳本

[root@centos7 ~]# cat install_httpd.sh 
#!/bin/bash
#
#******************************************************************************
#Author:        zhanghui
#QQ:            19661891
#Date:          2021-02-28
#FileName:      install_httpd.sh
#URL:           www.cnblogs.com/neteagles
#Description:   install_httpd for centos 7/8 & ubuntu 18.04/20.04
#Copyright (C): 2021 All rights reserved
#******************************************************************************
SRC_DIR=/usr/local/src
COLOR="echo -e \\033[01;31m"
END='\033[0m'
CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'`

APR_URL=https://mirrors.cloud.tencent.com/apache/apr/
APR_FILE=apr-1.7.0.tar.gz
APR_UTIL_URL=https://mirrors.cloud.tencent.com/apache/apr/
APR_UTIL_FILE=apr-util-1.6.1.tar.gz
HTTPD_URL=https://mirrors.cloud.tencent.com/apache/httpd/
HTTPD_FILE=httpd-2.4.48.tar.gz
INSTALL_DIR=/apps/httpd
MPM=event

os(){
    if grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release;then
        rpm -q redhat-lsb-core &> /dev/null || { ${COLOR}"安裝lsb_release工具"${END};yum -y install  redhat-lsb-core &> /dev/null; }
    fi
    OS_ID=`lsb_release -is`
}

check_file(){
    cd  ${SRC_DIR}
    if [ ${OS_ID} == "CentOS" ] &> /dev/null;then
        rpm -q wget &> /dev/null || yum -y install wget &> /dev/null
    fi
    if [ ! -e ${APR_FILE} ];then
        ${COLOR}"缺少${APR_FILE}文件"${END}
        ${COLOR}"開始下載${APR_FILE}源碼包"${END}
        wget ${APR_URL}${APR_FILE} || { ${COLOR}"下載${APR_FILE}源碼包下載失敗"${END}; exit; }
    else
        ${COLOR}"${APR_FILE}文件已准備好"${END}
    fi
    if [ ! -e ${APR_UTIL_FILE} ];then
        ${COLOR}"缺少${APR_UTIL_FILE}文件"${END}
        ${COLOR}"開始下載${APR_UTIL_FILE}源碼包"${END}
        wget ${APR_UTIL_URL}${APR_UTIL_FILE} || { ${COLOR}"下載${APR_UTIL_FILE}源碼包下載失敗"${END}; exit; }
    else
        ${COLOR}"${APR_UTIL_FILE}文件已准備好"${END}
    fi
    if [ ! -e ${HTTPD_FILE} ];then
        ${COLOR}"缺少${HTTPD_FILE}文件"${END}
        ${COLOR}"開始下載${HTTPD_FILE}源碼包"${END} 
        wget ${HTTPD_URL}${HTTPD_FILE} || { ${COLOR}"下載${HTTPD_FILE}源碼包下載失敗"${END}; exit; }
    else
        ${COLOR}"${HTTPD_FILE}文件已准備好"${END}
    fi
}

install_httpd(){
    [ -d ${INSTALL_DIR} ] && { ${COLOR}"Httpd已存在,安裝失敗"${END};exit; }
    ${COLOR}"開始安裝Httpd"${END}
    ${COLOR}"開始安裝Httpd依賴包"${END}
    if [ ${OS_ID} == "CentOS" ] &> /dev/null;then
        yum -y install gcc make pcre-devel openssl-devel expat-devel wget bzip2 &> /dev/null
    else
        apt update&> /dev/null
        apt -y install gcc make libapr1-dev libaprutil1-dev libpcre3 libpcre3-dev libssl-dev wget &> /dev/null
    fi
    tar xf ${APR_FILE} && tar xf ${APR_UTIL_FILE} && tar xf ${HTTPD_FILE}
    APR_FILE_DIR=`echo ${APR_FILE}_| sed -nr 's/^(.*[0-9]).*/\1/p'`
    APR_UTIL_FILE_DIR=`echo ${APR_UTIL_FILE}_| sed -nr 's/^(.*[0-9]).*/\1/p'`
    HTTPD_FILE_DIR=`echo ${HTTPD_FILE}_| sed -nr 's/^(.*[0-9]).*/\1/p'`
    mv ${APR_FILE_DIR} ${HTTPD_FILE_DIR}/srclib/apr
    mv ${APR_UTIL_FILE_DIR} ${HTTPD_FILE_DIR}/srclib/apr-util
    cd ${HTTPD_FILE_DIR}
    ./configure --prefix=${INSTALL_DIR} --enable-so --enable-ssl --enable-cgi --enable-rewrite --with-zlib --with-pcre --with-included-apr --enable-modules=most --enable-mpms-shared=all --with-mpm=${MPM}
    make -j ${CPUS} && make install
    [ $? -eq 0 ] && $COLOR"Httpd編譯安裝成功"$END ||  { $COLOR"Httpd編譯安裝失敗,退出!"$END;exit; }
    useradd -s /sbin/nologin -r apache
    sed -i 's/daemon/apache/' ${INSTALL_DIR}/conf/httpd.conf
    echo "PATH=${INSTALL_DIR}/bin:$PATH" > /etc/profile.d/http24.sh
    . /etc/profile.d/http24.sh
    cat > /lib/systemd/system/httpd.service <<-EOF
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=man:httpd(8)
Documentation=man:apachectl(8)

[Service]
Type=forking
ExecStart=${INSTALL_DIR}/bin/apachectl start
ExecReload=${INSTALL_DIR}/bin/apachectl graceful
ExecStop=${INSTALL_DIR}/bin/apachectl stop
KillSignal=SIGCONT
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF
    systemctl daemon-reload
    systemctl enable --now httpd &> /dev/null
    systemctl is-active httpd &> /dev/null ||  { ${COLOR}"httpd 啟動失敗,退出!"${END} ; exit; }
    ${COLOR}"httpd安裝完成"${END}
}

main(){
    os
    check_file
    install_httpd
}

main

六.請解釋一下以下response header各行的含義?

Date Tue,22Feb 2011 04:37:45 GMT	#報文的創建時間
Server Apache	#服務器程序軟件名稱
Last-Modified Thu,04 Nov 2010 04;12:24 GMT	#最后一次修改的時間
Etag"9fc-10c-82-5d73fa00”	#實體的擴展標簽
Content-Length 130	#主體的長度
Cache-Control max-age-2592000	#控制緩存時長
Expires Thu,24 Mar 2011 04:37:45 GMT	#實體的過期時間
Age 21190	#從最初創建開始,響應持續時長
X-Cache HIT from 86-74.ul.sinaimg.cn	#表示從CDN訪問
Via 1.0.86-74.ul.sinaimg.cn:80(squid/2.6.STABLE21)	#:顯示報文經過的中間節點(代理,網關)
Connection keep-alive  #連接狀態:持久連接

七.http協議常用的狀態碼

200: 成功,請求數據通過響應報文的entity-body部分發送;OK
301: 請求的URL指向的資源已經被刪除;但在響應報文中通過首部Location指明了資源現在所處的新位置;Moved Permanently
302: 響應報文Location指明資源臨時新位置 Moved Temporarily
304: 客戶端發出了條件式請求,但服務器上的資源未曾發生改變,則通過響應此響應狀態碼通知客戶端;Not Modified
307: 瀏覽器內部重定向
401: 需要輸入賬號和密碼認證方能訪問資源;Unauthorized
403: 請求被禁止;Forbidden
404: 服務器無法找到客戶端請求的資源;Not Found
500: 服務器內部錯誤;Internal Server Error
502: 代理服務器從后端服務器收到了一條偽響應,如無法連接到網關;Bad Gateway
503: 服務不可用,臨時服務器維護或過載,服務器無法處理請求
504: 網關超時


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM