Nginx (web server,web reverse proxy):
http協議:80/tcp,HyperText Transfer Procotol
http協議版本:
HTTP/0.9:原型版本,功能簡陋
HTTP/1.0:第一個廣泛使用的版本,支持MIME
HTTP/1.1: 增強了緩存功能
spdy
HTTP/2.0 下一次流行
MIME:Multipurpose Internet Mail Extesion 多用途互聯網郵件擴展
major/minor:text/plain, text/html, image/jpeg
URI: Uniform Resource Identifier 同一資源標識符
URL: Uniform Resorce Locator(統一資源定位符),用於描述某服務器某特定資源的位置;
URL包括三部分:
URL方案:scheme//
服務器地址:ip:port
資源路徑:
http://www.magedu.com:80/bbs/index.php,
https://就表示scheme,表示用什么協議進行交換
Scheme://Server:Port/path/to/resource
http://www.magedu.com/images/logo.jpg
URN: Uniform Resource Naming
http事務:httpd一次請求和響應的過程
請求:request //請求是由請求報文來請求
響應:response//響應是由響應報文來構建
報文語法格式:
request報文
<method> <request-URL> <version> //起始行
<headers> //有可能由眾多的頭部組成
<entity-body> //請求主體部分,有可能為空
Response響應報文
<version> <status> <reason-phrase>原因短語
<headers>
<entity-body>//響應實體
請求報文語法解析:
method:請求方法,標明客戶端希望服務器對資源執行的動作
GET(表示客戶端希望服務器把資源打包發給客戶端)、HEAD、POST
version://請求報文和響應報文都一樣
HTTP/<major>.<minor>//主版本號.次版本號
status:
三位數字,如200,301, 302, 404, 502; 標記請求處理過程中發生的情況;
reason-phrase:
status狀態碼所標記的狀態的簡要描述;
headers:首部
每個請求或響應報文可包含任意個首部;每個首部都有首部名稱,后面跟一個冒號,而后跟上一個可選空格,接着是一個值;
entity-body:請求時附加的數據或響應時附加的數據;有用的數據塊,請求報文entity-body可能為空
method(方法):
GET:從服務器獲取一個資源;
HEAD:只從服務器獲取文檔的響應首部,而不是響應內容;
POST:向服務器發送要處理的數據,放在<entity-body>中;
PUT:將請求的主體部分存儲在服務器上,上傳數據到服務器;
DELETE:請求刪除服務器上指定的文檔;
TRACE:追蹤請求到達服務器中間經過的代理服務器;
OPTIONS:請求服務器返回對指定資源支持使用的請求方法,如get等;
status(狀態碼):
1xx:100-101, 額外信息提示;
2xx:200-206, 成功類的響應;
3xx:300-305, 重定向類的狀態;
4xx:400-415, 錯誤類信息,客戶端錯誤(客戶端請求根本不存在的資源)
5xx:500-505, 錯誤類信息,服務器端錯誤(服由於自己內部問題,導致運行不成功)
常用的狀態碼:
200: 成功,請求的所有數據通過響應報文的entity-body部分發送;OK
301: 請求的URL指向的資源已經被刪除;但在響應報文中通過首部Location指明了資源現在所處的新位置;Moved Permanently,永久重定向
302: 與301相似,但在響應報文中通過Location指明資源現在所處臨時新位置;Found,資源有,需要重新找
304: 客戶端發出了條件式請求,但服務器上的資源未曾發生改變,則通過響應報文此響應狀態碼通知客戶端;Not Modified
401: 需要輸入賬號和密碼認證方能訪問資源;Unauthorized未認證
403: 請求被禁止;Forbidden
404: 服務器無法找到客戶端請求的資源;Not Found
500: 服務器內部錯誤,原因很多;Internal Server Error
502: 代理服務器從后端服務器收到了一條偽響應;
504
Gateway Timeout
是一種HTTP協議的服務器端錯誤狀態代碼,表示扮演網關或者代理的服務器無法在規定的時間內獲得想要的響應。
Bad Gateway表示客戶端向代理服務器發送請求,代理服務器應該給客返回結果,但是代理服務器本地沒有緩存,就像上游代理服務器請求,上游服務器給所請求的下游服務器發送了一個錯誤的,因此下游服務器就沒辦法響應客戶端。
協議查看或分析的工具:tcpdump, tshark, wireshark
方法是客戶端告訴服務器端應該做什么,狀態碼是服務器端告訴客戶端的請求發生的狀態
headers:
格式: Name:Value
首部的分類:
通用首部、請求首部、響應首部、實體首部、擴展首部
通用首部:
Date: 報文的創建時間
Connection:連接狀態,如keep-alive, close
Via:顯示報文經過的中間節點
Cache-Control:控制緩存生效機制
Pragma:
請求首部:
Accept:通過服務器自己可接受的媒體類型;
Accept-Charset:
Accept-Encoding:接受編碼格式,如gzip
Accept-Language:接受的語言
Client-IP:
Host: 請求的服務器名稱和端口號
Referer:包含當前正在請求的資源的上一級資源;
User-Agent:客戶端代理
條件式請求首部:
Expect:期望發什么信息
If-Modified-Since:自從指定時間之后,請求的資源是否發生過修改;
If-Unmodified-Since:自從指定時間之后,請求的資源沒有發生修改;
If-None-Match:本地緩存中存儲的文檔的ETag(擴展標簽)標簽是否與服務器文檔的Etag不匹配;是:表示不匹配,否:表示匹配
If-Match:和If-None-Match相對應
安全請求首部:
Authorization:向服務器發送認證信息,如賬號和密碼;
Cookie: 客戶端向服務器發送cookie
Cookie2:
代理請求首部:
Proxy-Authorization: 向代理服務器認證
響應首部:
信息性:
Age:響應持續時長
Server:服務器程序軟件名稱和版本
協商首部:某資源有多種表示方法時使用
Accept-Ranges:服務器可接受的請求范圍類型
Vary:服務器查看的其它首部列表;
安全響應首部:
Set-Cookie:向客戶端設置cookie;
Set-Cookie2:
WWW-Authenticate:來自服務器的對客戶端的質詢認證表單
實體首部:
Allow: 列出對此實體可使用的請求方法
Location:告訴客戶端真正的實體位於何處,在重定向時使用
Content-Encoding:內容編碼格式
Content-Language:內容使用語言
Content-Length: 主體的長度
Content-Location: 實體真正所處位置;
Content-Type:主體的對象類型
緩存相關:
ETag:實體的擴展標簽;
Expires:實體的過期時間;
Last-Modified:最后一次修改的時間
http協議是文本編碼的是無狀態的
web資源
靜態資源:靜態內容;客戶端從服務器獲得的資源的表現形式與原文件相同;
動態資源:通常是程序文件,需要在服務器執行之后,將執行的結果返回給客戶端;客戶端拿到的內容依然是靜態的,認識純文本,跟服務器端不一樣
Web服務器和程序解釋器之間是如何協調工作的?即web服務器如何把客戶端請求的動態資源讓解釋器去磁盤調用並進行運行?他們之間遵循一種協議:CGI。
通俗的可以把服務器看作餐廳,用戶請求看作來用餐的顧客,服務器處理請求看作解決顧客的就餐問題(響應輸出一份飯)。
服務器上靜態資源看作已做好的飯,只要放到餐盒里就可以返回給顧客,動態資源需要廚房大廚現成做份再放到餐盒里返回給顧客。
php_mod:這個大廚有個特點,看見有顧客進門就點火,不管顧客要不要現做的,有點浪費資源
php_fpm:這個大廚有好多小弟一直點着火(多個處理進程),等有顧客說要現做,大廚就安排小弟做份返回給客戶
cgi:也是個大廚,不過他等到顧客要現做,他才點火,做飯,然后熄火。等待下一個要現做的到來
fastcgi:就是個大廚雇了一幫小弟,專門做需要現場做的飯,大廚只管分派任務,小弟真正操鍋做飯
參考鏈接:https://www.zhihu.com/question/30672017/answer/53238751
程序=指令+數據
請求流程:Client --> (http) --> httpd服務 --> (cgi) --> application server (program file) --> (mysql驅動和協議) --> mariadb
1、首先客戶端A通過http協議請求資源,web服務器端B接受協議之后,通過過濾器識別客戶端請求的資源后綴,假如客戶端請求的動態資源,發現是.php,那么就向后轉發,通過CGI協議跟PHP解釋器的應用程序C進行交互,這時web服務器是CGI的客戶端,而php解釋器的應用程序是CGI的服務器端。
2、CGI服務器C上面運行的程序發現代碼中需要用到數據,服務器C會基於驅動D跟后面的數據存儲打交道,這時假如后面的是mysql服務器(都是應用層協議),那么中間用到的協議就是mysql協議。這時候,應用程序C就MySQL協議的客戶端,而MySQL服務器就成了MySQL協議的服務器端。
整個執行過程:客戶端請求一個動態資源,請求先送到給web服務器,web服務器發現這是一個動態資源,那么web服務器就會轉交給應用程序服務器-PHP程序,web服等待php程序響應,這個過程就被阻塞了,php程序就從磁盤上加載程序文件到php程序里面進行執行,在執行過程中,如果有結果就返回給web服務器,但是如果在執行過程中發現有數據,而數據在本地磁盤中並沒有存放,需要到MySQL服務器中去調用,於是php程序就扮演成MySQL服務器的客戶端發出請求,MySQL服務器經過對數據出來把結果返回給php應用程序,php程序對結果做進一步處理然后把結果返回給web服務器,web服務器把結果封裝成http報文發送到客戶端。
httpd的特性:
高度模塊化:core + modules
DSO: Dynamic Shared Object
MPM:Multipath Processing Modules //多路處理模塊
prefork:多進程模型,每個進程響應一個請求;
一個主進程:負責生成n個子進程,子進程也稱為工作進程,每個子進程處理一個用戶請求;即便沒有用戶請求,也會預先生成多個空閑進程,隨時等待請求到達;最大不會超過1024個;
worker:多線程模型,每個線程響應一個請求;
一個主進程:生成多個子進程,每個子進程負責生成多個線程,每個線程響應一個請求;
m進程,n線程:m*n
event:事件驅動模型,每個進程響應n個請求;
一個主進程:生成m個子進程,每個進程直接n個請求;
m*n
httpd-2.2:event為測試使用
httpd-2.4:event可生產使用
pv:page view
uv: user view
獨立IP
一個域名打開的線程數是有限的,所以有些網站為了提高用戶體驗就在一個網站頁面上布置多個域名
I/O類型:
參考:馬哥視頻、https://www.jianshu.com/p/786d351e06d8、https://www.jianshu.com/p/486b0965c296
同步和異步:synchronous, asyncrhonous
關注的是消息通知機制(被調用者即服務器端如何把已經完成的結果通知給調用者); 即服務器端
同步:調用發出不會立即返回,但一旦返回就可以返回最終結果;
異步:調用發出之后,被調用方立即返回消息,但返回的非最終結果;被調用者通過狀態、通知機制等來通知調用者,或通過回調函數來處理結果;
阻塞和非阻塞:block, nonblock
關注的是調用者等待被調用返回結果(消息、返回值)時的狀態 即客戶端
阻塞:調用結果返回之前,調用者(調用線程)會被掛起;調用者只有在得到結果之后才會返回;
非阻塞:調用結果返回之前,調用者不會阻塞當前線程;
5種I/O模型:prefork和worker都是復用型I/O,並發能力有限,最多1024;event是事件驅動型I/O;
blocking IO 阻塞式IO
nonblocking IO 非阻塞式IO
以上兩種IO模型中第二階段需要調用者即進程等待內存把數據從內核內存中復制給進程內存,這個過程調用者是阻塞的
IO multiplexing 復用型IO //把請求給內核代理,不是給內核,請求最多1024個,阻塞在select上,這樣的好處調用者可以繼續發送請求;
select(),poll()
signal driven IO 事件驅動式IO 當用戶請求的數據准備好之后,內核會通知進程取數據,如果這時進程在第二階段被阻塞時,如何?內核通知進程后,過了指定時間就會消失。
之所以叫事件驅式IO,是因為一旦數據從磁盤到內核內存即數據准備好了之后,內核會通知調用者即調用進程,讓調用者就會使用回調函數進行處理。
(第二段阻塞:因為內核把數據准備好后,會通知進程數據已准備好,這是進程就要准備接受數據,然后內核會把數據從內核內存復制到進程內存)
通知機制:水平觸發:通知一次沒響應,再通知,直到你處理為止;
邊緣觸發:只通知一次,如果沒有響應,就把通知事件通過回調函數讓調用者自行來獲取,即把通知信息放在某處;
復用IO和事件驅動IO模型第二階段之所以阻塞是因為第一階段:在內核從磁盤把數據處理好后放到內核內存后,第二階段就需要調用者即進程調用回調函數來內核內存中取數據,所以也是阻塞。
asyncrhonous IO 異步IO 第二階段即內存把數據准備好后,不需要調用者再利用回調函數去內核內存中取數據,而是內存直接把數據復制到進程內存中。
例:一個read操作:
(1) 等數據准備好,從磁盤到內核內存;
(2) 從內核內存復制到進程內存;
一個磁盤IO分兩步:
1、用戶空間的進程沒有權限直接訪問硬件的,用戶空間的進程發起IO調用時,只能向內核請求,數據只能在硬盤上,內核先把數據加載至內存內存中,
2、內核再把數據從內核內存復制到進程內存
這兩步真正執行IO的是數據從內核內存到進程內存 真正稱為IO的步驟是數據從內核內存到進程內存
沒有消息通知的是同步I/O:阻塞式I/O、非阻塞式I/O、復用型IO
有消息通知的是異步I/O: 事件驅動式IO、異步IO
nginx用的是事件驅動式IO,而且基於邊緣觸發通知機制來實現,同時也支持異步IO,而且還能夠完成基於內存映射機制來完成數據的發放。
一次完整的HTTP事務是怎樣一個過程? http://blog.51cto.com/linux5588/1351007 tcp三次握手 https://blog.csdn.net/geecky/article/details/56275032