nginx與http學習筆記

基本命令
start nginx
nginx -s stop(當即中止)
nginx -s quit(平緩中止,有請求事不會意外中止)
nginx -s reload
遇到的坑:不要重複地去啓動多個nginx進程,這樣會致使你修改的nginx對應不上,能夠經過資源管理器殺掉進程javascript

http keepalive 長鏈接

短鏈接:TCP創建鏈接->請求資源->響應資源-> 關閉鏈接 每次請求都要經歷這樣的過程
長鏈接:創建一次鏈接後,每次請求都複用該鏈接。
並行鏈接:併發的短鏈接
http1.0中爲了支持長鏈接必須在請求頭中指定css

Connection:keep-alive

在 HTTP 1.1 中 全部的鏈接默認都是持續鏈接,除非特殊聲明不支持;如今大多數瀏覽器都默認是使用HTTP/1.1,因此keep-alive都是默認打開的html

Connection:close 指定不使用長鏈接

怎麼判斷一個請求數據接收完?
在響應頭中若是有Tansfer-Encoding:chunked則表示body爲流式輸出,會被分紅多個塊,每一個塊開始都會標識當前塊的長度,此時body不須要長度;若是是非chunked則按照content-length來接收數據;不然等到服務端主動斷開鏈接。
nginx中關於transfer-encoding的設置chunked_transfer_encoding on | off;
創建鏈接後服務端不是一直在等待下一次請求,經過nginx設置最大等待時間
nginx: http模塊中能夠設置超大等待時間
keepalive_timeout 65;java

pipeline流水線做業
http1.1新特性,一個鏈接作屢次請求;
在keepaiive中第二個請求要等第一個請求響應徹底接受以後才能發起。
在pipeline中沒必要等待第一個請求處理後就能夠發起第二個請求,nginx會把讀取的數據放在buffer中,在nginx處理完第一個請求時發現buffer中還有數據,就會任務剩下的數據是下一個請求的開始,而後處理下一個請求,不然設置爲keepalivenode

擴展:TCP的keepalive:
AB在三次握手創建TCP鏈接以後,B忽然宕機了,可是A內核還會維護着AB之間的鏈接,浪費系統資源。引入keepalive機制,A定時給B發送空數據包,稱爲心跳包,一旦發現B網絡不通則關閉鏈接。
Nginx涉及到tcp層面的keepalive只有一個:so_keepalivenginx

nginx請求處理流程

Http處理過程
初始化http request(讀取客戶端數據,生成HTTP Request對象,該對象包含了全部請求信息)
處理請求頭
處理請求體
調用此請求的url或者location關聯的handle
依次調用各phase handler處理(phase handler是指包含某階段若干個handler)正則表達式

一個phase handler處理的任務chrome

  1. 獲取location配置
  2. 產生適當的響應
  3. response header
  4. response body

當nginx讀取到一個http Request的header時,首先尋找與請求關聯的虛擬主機配置,若是找到則經歷如下幾個phase handler
1.server級別的url重寫階段,在讀取請求頭過程當中nginx會根據host和端口尋找對應的虛擬主機配置:json

server{
    rewrite 規則 定向路徑 重寫類型
    # 訪問 /last.html 的時候,頁面內容重寫到 /index.html 中
    rewrite /last.html /index.html last;
}
    
規則:字符串或者正則來匹配目標url
定向路徑:匹配到規則後要定向的url
重寫類型:

 1. last 完成重寫瀏覽器地址欄url不變
 2. break終止後面的匹配,地址欄url不變
 3. redirect 302臨時重定向,地址欄顯示跳轉後的url
 4. permanent 301永久重定向,顯示跳轉後的url

2.location rewrite瀏覽器

  1. 執行server rewrite
  2. 執行location匹配
  3. 執行location rewrite

location 與 location rewrite的區別:

  • location是對一類資源控制訪問和反向代理,proxy_pass到其餘機器,location rewrite則是更改資源獲取路徑
rewrite regex replacement [flag];
1.重寫帶http://
location /{
    # 當匹配 正則表達式 /test/(.*)時 請求將被臨時重定向到 http://www.$1.com
    rewrite /test/(.*) http://www.$1.com
    return 200 'ok'
}
# 在瀏覽器中輸入 127.0.0.1:8080/test1/baidu 
# 則臨時重定向到 www.baidu.com
# 後面的 return 指令將沒有機會執行了
2.重寫不帶http://
location / {
    rewrite /test/(.*) www.$1.com;
    return 200 "ok";
}
# 發送請求以下
# curl 127.0.0.1:8080/test/baidu
# ok

# 此處沒有帶http:// 因此只是簡單的重寫。請求的 uri 由 /test/baidu 重寫爲 www.baidu.com
# 由於會順序執行 rewrite 指令 因此 下一步執行 return 指令 響應了 ok

TCP優化

http {
    sendfile           on;
    tcp_nopush         on;
    tcp_nodelay        on;

    keepalive_timeout  60;
    ... ...

senfile on能夠提升靜態資源託管效率,是一個系統調用,不須要先read再write,沒有上下文切換開銷
tcp_nopush 在sendfile開啓後才生效,啓用後數據包累計必定的大小纔會發送,提升了網絡效率,減小了開銷
tcp_nodelay 數據包累計到必定大小後儘快發送,nginx只會針對處於keepalive的TCP鏈接啓用tcp_nodelay
keepalive_timeout 表示每一個tcp鏈接能夠保持多少秒,默認是75秒,有些瀏覽器最可能是保持60秒,因此設置爲60秒

TFO(TCP Fast open)優化策略

clipboard.png

客戶端第一次創建鏈接仍是要三次握手,不一樣的是客戶端會在第一個SYN設置一個fast-open的標誌,服務端會生成fast-open cookie並放在SYN-ACK中,客戶端就能夠把cookie存起來之後syn用;
在這以後用戶再創建TCP鏈接,發送syn包的同時會把cookie帶上,而後能夠直接帶上http數據。換句話說在發送SYN包的時候把應用層數據發送出來,減小了一個RTT對性能的影響。
可是這種優化成本很是高須要操做系統、內核的支持(服務端和用戶端都要支持)。

開啓gzip

http {
    gzip               on;
    gzip_vary          on;

    gzip_comp_level    6;
    gzip_buffers       16 8k;

    gzip_min_length    1000;
    gzip_proxied       any;
    gzip_disable       "msie6";

    gzip_http_version  1.0;

    gzip_types         text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
    ... ...
}

gzip_vary 用來輸出vary響應頭解決某些服務緩存問題

  • http內容協商機制,同一個url可能對應多份不一樣文檔,要求服務端和客服端有一個選擇最合適版本的機制。例如服務端能夠將靜態文件輸出爲壓縮和未壓縮兩個版本。
  • 通常使用的方案是服務端根據客戶端請求頭的某些字段發送最合適的版本。分爲內容專用字段(Accept字段)、其餘字段
//請求頭
Accept:*/* 接受任何MIME類型資源
Accept-Encoding:gzip,deflate,sdch 接受gzip,deflate,sdch壓縮過的資源
Accept-Language:zh-CN,en-US;q=0.8,en;q=0.6 能夠接受zh-ch,en-us,en;其中zh-cn的優先級最高(q 取值 0 - 1,最高爲 1,最低爲 0,默認爲 1),服務端應優先返回zh-cn

//響應頭
Content-Type: text/javascript 表示文檔確切的類型是text/javascript
Content-Encoding: gzip 文檔使用了gzip壓縮
//沒有content-language一般表示返回的是Accept-language權重最高的那種語言

Accept字段並不夠用,若是要針對特定瀏覽器,如ie6就要使用到user-agent;cookie也可能做爲服務器輸出內容差別的依據。
若是服務器和客戶端之間存在有緩存服務器,而服務器根據不一樣的user-agent返回不一樣的內容,緩存服務器卻把針對特定瀏覽器的內容緩存下來統一返回,就會有問題。
因此http協議規定,若是服務器提供的內容是取決於user-agent(Accept以外的字段)請求頭字段,響應頭中必需要包含vary字段,並且vary字段必須包含user-agent。

//當內容取決於User-Agent和cookie時,vary字段應該相似於這樣,也就是列出一個響應字段列表,告訴緩存服務器遇到同一個url的時候如何緩存和篩選合適的版本。
Vary:User-Agent, Cookie;

Content-Encoding在緩存服務器的問題
緩存服務器應該根據不一樣的Content-Encoding緩存不一樣的內容,再根據請求頭的Accept-Encoding來返回合適的版本。爲了不給客戶端返回不合適的版本:
1.將請求頭的Cache-control改成private
2.增長vary:Accept-Encoding明確告訴緩存服務器按照Accept-Encoding字段內容緩存不一樣的版本。

以上的工做nginx都以gzip_vary: on搞定,至關於在啓用了gzip的響應上加vary:Accept-Encoding

gzip_disable
接受一個正則匹配,請求的User-Agent匹配到後響應不會啓用gzip。是爲了解決某些瀏覽器啓用gzip帶來的問題。

gip_http_version
nginx默認啓用http版本是Http/1.1,由於早期Http/1.0啓用gzip有bug,如今基本忽略,全部能夠指定gzip_http_version: 1.0;

開啓緩存
優化代碼邏輯的極限是移除全部極限;優化請求的極限是不發送任何請求。

http{
    proxy_cache_path /home/nginx/proxy_cache_path levels=1:2 keys_zone=pnc:300m inactive=7d max-size=10g;
}

/home/nginx/proxy_cache_path: 本地路徑,緩存文件存放的路徑
levels:默認全部文件放在/home/nginx/proxy_cache_path下,影響緩存性能,大部分場景是推薦使用2級目錄來緩存文件。

post請求提交數據的四種格式
http協議規定post方法提交的數據主體必須方式消息主體中(entity-body),可是協議並無規定數據必須使用什麼編碼格式。開發者能夠本身決定主體內容。服務器都內置瞭解析常見數據格式的功能,根據請求頭的content-type來獲取消息中的請求消息主體是以何種方式編碼,再對主體進行解析。
Content-Type

  1. application/x-www-form-urlencoded

    • 原生的form提交不設置enctype屬性時默認使用這種格式提交,提交格式按照val1=key1&val2=key2格式進行編碼,key和val都進行了url轉碼。

      POST http://www.example.com HTTP/1.1
      Content-Type: application/x-www-form-urlencoded;charset=utf-8
      title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
  2. multipart/form-data

    • 在form表單上傳文件的時候必須設置enctype爲這個格式。首先生成boundary用於分割不一樣字段。Content-type中指明瞭數據是以multipart/form-data來編碼,boundary是什麼。
    • 消息主體中按照字段的個數又分爲多個相似結構的部分,每部分都是以--boundaey開頭,緊接着內容描述信息,而後回車最後是字段具體內容(文本或者二進制)。
    • 若是傳輸的是文件,還要包括文件名和文件類型信息。消息主體最後以--boundary--結束。

      POST http://www.example.com HTTP/1.1
      Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
      
      ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
      Content-Disposition: form-data; name="text"
      
      title
      ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
      Content-Disposition: form-data; name="file"; filename="chrome.png"
      Content-Type: image/png
      
      PNG ... content of chrome.png ...
      ------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
  3. application/json

    • 告訴服務器消息主體是序列化後的json字符串
  4. text/html
相關文章
相關標籤/搜索