1. 程式人生 > >《深入理解nginx》總結

《深入理解nginx》總結

nginx設計中的效能優化點

一些指標

  • 10000個非活躍 http keep alive 連線在nginx消耗2.5MB記憶體
  • 單機支援10萬以上並非連線

和nginx有關的核心調優:

可以修改/etc/sysctl.conf來更改核心引數調優

  • file-max: 一個程序最大可以開啟的檔案控制代碼數, 這個引數直接限制了nginx的最大併發連線數
  • tcp-tw-reuse: 設定為1時表示允許將time-wait狀態的socket重新新的tcp連線。 ps. 記憶體方面現在linux已經優化的很好, 處於time-wait狀態的socket只佔用很少的記憶體, 釋放/複用埠最重要, 畢竟埠數就就那些。
  • tcp-keepalive-time: 當keep-alive啟用時,tcp傳送keep-alive訊息的頻率, 預設兩小時, 設定的低一些可以更快清理無效連線。
  • tcp_fin_timeout: 伺服器主動斷開連線時, socket保持在fin-wait-2狀態的最大時間
  • tcp_max_sync_backlog: syn佇列最大長度
  • ip_local_port_range: tcp/udp埠取值範圍(是設定本地, 不能設定遠端)
  • net.ipv4.tcp_rmem/net.ipv4.tcp_wmem: tcp接受/傳送滑動視窗的最小值, 最大值, 預設值
  • netdev_max_backlog: 網絡卡接收資料包的速度大於核心處理速度時, 有一個佇列儲存這些資料包, 這個引數表示佇列最大值
  • rmem_default/wmwm_default: 核心套接字接收/傳送快取區的預設大小
  • rmem_max/wmem_max: 核心套接字接收/傳送快取區的最大大小

nginx為訪問第三方服務做的優化

在用nginx開發模組時,如果需要訪問第三方服務, 不能自己簡單的用套接字程式設計, 會破壞nginx全非同步架構。nginx提供了兩種全非同步通訊方式:
upstream: 它把nginx定義成代理伺服器, 首要功能時透傳。 nginx反向代理功能就是基於此。
subrequest用於處理請求派生出的子請求
兩者區別: 比如實現頻控模組要去redis讀寫資料, 這就是一個子請求, 在非同步收到響應後, 如果通過頻控, 就需要將請求透傳給上游, 此時用upstream

配置搜尋優化

server 配置通過hash表搜尋
location塊通過二叉樹搜尋, 因為是靜態的,不會變, 所以不用紅黑樹, 用的完全平衡二叉樹

記憶體池:

  • 用於減少系統呼叫次數;

  • 如何避免gc機制: 開發者申請一個記憶體池後可以從中任意申請記憶體, 最後用完銷燬記憶體池即可。 nginx是一個web伺服器, 每一個請求的生命週期很短, 也決定了每個記憶體池的生命週期短, 因此不會累積過多沒有銷燬的記憶體池。而在開發模組時,直接使用ngx_poll_t即可, 模組結束後自動釋放。 ps. 感覺rust的生命週期, 所有權也是類似思想, 超過生命週期就銷燬,只不過rust是語言去檢查生命週期, nginx這裡需要自己檢查, 不用像go java需要另外執行緒/協程 去gc。

  • 申請大記憶體和小記憶體的不同處理: 當nginx判斷申請記憶體大(x86 大於4095位元組)的時候, 直接從堆上申請記憶體,掛到一個大記憶體連結串列上,大記憶體的生命週期可能遠遠小於請求的生命週期的情況就需要nginx考慮了, nginx提供了方法提前釋放大類存而不用等到記憶體池銷燬。
    小塊記憶體niginx會一次申請比較大的一塊, 後面複用。

  • 記憶體對齊,碎片整理: p281 ~ p283 重點看p283流程圖

事件:

  • 網路事件: epoll
  • 定時事件器: 紅黑樹實現, 按照每個任務的時間來排序, 每次取最左邊的節點的時間和當前時間判斷即可。呼叫ngx_event_expire_timers方法觸發所有超時事件。
  • 磁碟事件: linux 真.非同步io,書裡面吐槽了下glic裡的非同步io是多使用者執行緒實現的,假非同步io, 而nginx的讀操作用的是linux核心實現, 只有在核心程序中完成了磁碟操作, 核心才會通知nginx程序。 這樣的好處一方面是可以讓nginx更充分佔用cpu, 另一方面當有大量讀磁碟的事件堆積到核心的時候,核心可以通過“電梯演算法”降低隨機讀磁碟的成本。
    為啥是讀操作採用非同步而寫操作不採用呢? 因為linux非同步磁碟io寫操作不支援快取, 也就是每次使用者程序都要寫到磁碟上去, 這樣更慢。

程序模型:

  • master-woker: nginx啟動時master程序進行初始化讀取配置檔案後fork出worker程序來監聽處理網路事件, 因為時fork出來的, 所以和master監聽的是同意個埠, accept事件到來時會有爭搶。
    • master程序不負責網路事件的監聽和處理, 主要是負責啟動服務, 平滑升級, 更換日誌檔案, 熱更新配置等, 管理woker等功能。 是通過訊號來管理woker程序。(說白了就是設定標誌位)
    • woker程序監聽和處理網路事件, 一個woker掛了時master會快速拉起一個新woker
    • 一個優化, nginx通常執行緒數和核心數相當, 可以配置程序繫結cpu, 減少程序在cpu間的越遷, 高效利用cpu cache
  • 驚群問題: nginx 會fork 多個子程序監聽同一個埠, 子程序在accept建立新連線時會爭搶,程序數量多時會有效能下降。
    開accept_mutex鎖(預設開啟)解決。 nginx通過一個程序間同步鎖accept_mutex, 保證同一時刻只能由一個woker在監聽web埠。釋放鎖通過定時器事件來實現。
  • 程序間負載均衡問題:多個woker搶一個事件時, 會有一個成功, 但如果這個woker本來就已經堆積了大量事件,另外有空閒程序或者任務少的程序搶不到事件, 子程序間就出現了負載不均衡。
    開accept_mutex鎖解決(預設開啟), 每個woker有個變數ngx_accept_disabled, 初始為負值,絕對值為配置的總連線數的7/8, 每次使用一個連線就加1。這個值為正時觸發負載均衡,此時來accept事件時此woker不會去搶accept_mutex, 而是將ngx_accept_disabled 減一。 疑問, 為何是7/8?

TCP與ngixn(nginx基於tcp上的優化):

p342 全節重點

  • 基礎知識:
  1. 三次握手時的syn, accept佇列
  2. 使用者程序在呼叫核心send方法時的的流程圖 9-9
  3. recv方法的流程圖3. recv方法的流程圖
  • nginx的優化:
    使用者可調整核心記憶體快取的上限, p345 下面一段
    nginx也提供了記憶體自動調整功能, p347 圖, 相當於多了幾個閾值

再看upstream

  • client 到nginx和nginx到server間的網速是極不對稱的, 反向代理的一個重要功能就是, 提供大記憶體和磁碟檔案快取包, 按照一定策略,接受完一定大小的包後, 再由nginx發給client或server。 這樣做減少了server需要維持的連線和快取的佔用時間。
  • 與server:
    • 建立tcp連線三次握手是非同步的, 傳送syn後epoll註冊事件監聽, 設定回撥函式
    • 向上遊傳送請求或者接收下游請求時, 請求大小未知,所以傳送請求的方法需要被epoll排程多次後才能發/收完請求的全部內容。
    • 包頭大小有一個合理範圍, 而包體不一定,並且nginx不關心包體內容, 因此nginx將包頭全部用記憶體快取, 包體則根據情況而定
      -透傳請求: nginx將client的請求包體全部接收完後才發給server
    • 透傳響應: 可與配置三種模式:
      • 1.不轉發響應(不實現反向代理)
      • 2.轉發響應時上游網速優先: 若下游網速快於上游網速, 或者相差不大, 不需要nginx開闢大塊記憶體或磁碟檔案來快取上游響應
      • 3.轉發響應時下游網速優先: 開闢記憶體會磁碟快取響應

相關推薦

深入理解nginx總結

nginx設計中的效能優化點 一些指標 10000個非活躍 http keep alive 連線在nginx消耗2.5MB記憶體 單機支援10萬以上並非連線 和nginx有關的核心調優: 可以修改/etc/sysctl.conf來更改核心引數調優 file

轉載:2.2.3 配置項的註釋《深入理解Nginx》(陶輝)

href 深入 logs class tps 註釋 配置 blog bsp 原文:https://book.2cto.com/201304/19628.html如果有一個配置項暫時需要註釋掉,那麽可以加“#”註釋掉這一行配置。例如:#pid logs/ngi

轉載:2.2.5 在配置中使用變量《深入理解Nginx》(陶輝)

依賴 con com 關註 部分 自己 core stat sent 原文:https://book.2cto.com/201304/19630.html 有些模塊允許在配置項中使用變量,如在日誌記錄部分,具體示例如下。log_format main ‘$r

深入理解NGINX 模組開發與架構解析》之摘抄學習

1.基於Nginx框架開發程式有5個優勢:     (1).Nginx將網路、磁碟及定時器等非同步事件的驅動都做了非常好的封裝,基於它開發將可以忽略這些事件處理的細節;     (2).Nginx封裝了許多平臺無關的介面、容器,適用於跨平臺開發。

深入理解Nginx:模組開發與架構解析

讀書筆記 第一部分         Nginx能幫我們做什麼 第1章 研究Nginx前的準備工作         1.1Nginx是什麼         1.2

深入理解Nginx第八章:nginx基礎架構

Nginx效能指標 吞吐量(頻寬指的是單個連線的吞吐量) 單次請求的延遲性 網路效率:長連線減少建立、關閉連線的成本,壓縮演算法增加資訊攜帶量 Nginx  模組設計 NGX_CONF_MODULE:唯一隻有一個模組(ngx_conf_modul

推薦我的新書《深入理解Nginx:模組開發與架構解析》

.2.1 執行中的nginx程序間的關係 / 28  2.2 nginx配置的通用語法 / 31  2.2.1 塊配置項 / 31  2.2.2 配置項的語法格式 / 32  2.2.3 配置項的註釋 / 33  2.2.4 配置項的單位 / 33  2.2.5 在配置中使用變數 / 33  2.3 ngin

深入理解Nginx 模組開發與架構解析》筆記之epoll事件模組

epoll Linux epoll Linux epoll工作模式 水平觸發LT 邊緣觸發ET       前者是預設的,可以處理阻塞和非阻塞套接字,後者只能處理非阻塞套接字。 Linux epoll原理       如上

深入理解Nginx》閱讀與實踐(一):Nginx安裝配置與HelloWorld

#include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> static char* ngx_http_mytest(ngx_conf_t *cf,ngx_command_t *cmd,

深入理解Nginx的 模組化 ,全域性觀

Nginx原始碼目錄結構 . ├── auto 自動檢測系統環境以及編譯相關的指令碼 │ ├── cc 關於編譯器相關的編譯選項的檢測指令碼 │ ├

深入理解JVM總結——虛擬機器位元組碼執行引擎

執行引擎是Java虛擬機器最核心的組成部分之一。物理機和虛擬機器都有執行程式碼的能力。區別在於物理機的執行引擎是直接建立在處理器、硬體、指令集和作業系統層面上的,而虛擬機器的執行引擎則是由自己實現的,因此可以自行指定指令集與執行引擎的結構體系,並且能夠執行那些不

深入理解Nginx》讀書筆記1:架構設計

Nginx設計目標及優點 1、跨平臺的Web伺服器; 程式碼儘可能的與平臺無關,封裝呼叫多個主流作業系統的高效API提高效能。 2、高效響應請求; 單次響應更快,高峰期響應更快。支援高併發請求的同時保持高效服務。 3、高擴充套件性; 設計

深入理解JVM總結-JDK各版本、JVC記憶體分配及溢位異常

第一部分 走近JAVA 第一章 走近Java 1.JDK1.5版本改動非常大,加入了自動裝箱、泛型、動態註解、列舉、可變長引數以及遍歷迴圈等。     JDK1.6提供動態語言支援,提供API編譯,且JVM中改進了鎖與同步、垃圾收集以及類載入等的演算法。    JDK1.7

深入理解Nginx 模組開發與架構解析-陶輝 讀書筆記

前言 1. nginx是一個優秀的事件驅動框架,nginx非常適合開發在傳輸層以TCP對外提供服務的伺服器程式。基於nginx框架開發程式有5個優勢: * nginx將網路、磁碟及定時器等非同步事件的驅動都做了非常好的封裝,基於它開發將可以忽略這些事情處理的細節 * ng

深入理解Nginx》筆記之 HTTP請求的11個處理階段

HTTP請求的11個處理階段 typedef enum { // 接收到完整的HTTP頭部後處理階段 NGX_HTTP_POST_READ_PHASE = 0, // 將請求URI與location表示式匹配前,修改URI,即重定

深入理解Nginx:模組開發與架構解析 讀書筆記

Nginx的作用 當我們在設計高效能web伺服器的時候,我們第一選擇是使用Nginx,因為nginx對伺服器效能上的挖掘已經到了非常高的水平,Nginx採用了無阻塞分階段的事件驅動框架。當nginx不能那個完全實現我們的業務需求的時候,我們可以在Nginx後端搭建一個非ng

coreData 深入理解4 --總結 (執行緒安全與同步--iOS5 前後對比)

Core Data是iOS中很重要的一個部分,可以理解為基於SQLite(當然也可以是其他的Storage,如In-memory,只是SQLite比較常見)的一個ORM實現,所以有關係資料庫的特性,又不用寫SQL。順便吐一下槽,官方說法是使用Core Data能減少50%-70%的程式碼量,但相信用過的人

三:深入理解Nginx的模組化 (結合原始碼詳解)

盜用前面用到的流程圖 第二步實際上是呼叫 ngx_add_inherited_sockets() //檔名: Nginx.c int ngx_cdecl main(int argc,

深入理解Nginx及使用Nginx實現負載均衡

前言:   最近在部署專案時要求實現負載均衡,有趣的是發現網上一搜全部都是以下類似的配置檔案 upstream localhost{ server 127.0.0.1:8080 weight=1; server 127.0.0.1:8081 weight=1; } serve

深入理解Java虛擬機器》個人讀書總結——垃圾收集/回收演算法

說起垃圾回收,我估計很多初級java開發(包括之前的我)想到的是這個JVM會幫我管理的啊,我們不太需要去考慮這種事情。但是,當需要排查各種記憶體溢位、記憶體洩漏問題時,當垃圾收整合為系統達到更高併發量的瓶頸的時候,我們就有必要對垃圾回收GC進行了解了。思考GC需要完成的3件事情: 1.