1. 程式人生 > >推薦我的新書《深入理解Nginx:模組開發與架構解析》

推薦我的新書《深入理解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 nginx服務的基本配置 / 34 
2.3.1 用於除錯程序和定位問題的配置項 / 34 
2.3.2 正常執行的配置項 / 36 
2.3.3 優化效能的配置項 / 38 
2.3.4 事件類配置項 / 39 
2.4 用http核心模組配置一個靜態web伺服器 / 41 
2.4.1 虛擬主機與請求的分發 / 42 
2.4.2 檔案路徑的定義 / 45 
2.4.3 記憶體及磁碟資源的分配 / 48 
2.4.4 網路連線的設定 / 50 
2.4.5 mime型別的設定 / 53 
2.4.6 對客戶端請求的限制 / 54 
2.4.7 檔案操作的優化 / 55 
2.4.8 對客戶端請求的特殊處理 / 57 
2.4.9 ngx_http_core_module模組提供的變數 / 59 
2.5 用http proxy module配置一個反向代理伺服器 / 60 
2.5.1 負載均衡的基本配置 / 62 
2.5.2 反向代理的基本配置 / 64 
2.6 小結 / 68 
第二部分 如何編寫http模組 
第3章 開發一個簡單的http模組 / 70 
3.1 如何呼叫http模組 / 70 
3.2 準備工作 / 72 
3.2.1 整型的封裝 / 72 
3.2.2 ngx_str_t資料結構 / 73 
3.2.3 ngx_list_t資料結構 / 73 
3.2.4 ngx_table_elt_t資料結構 / 77 
3.2.5 ngx_buf_t資料結構 / 77 
3.2.6 ngx_chain_t資料結構 / 79 
3.3 如何將自己的http模組編譯進nginx / 79 
3.3.1 config檔案的寫法 / 80 
3.3.2 利用configure指令碼將定製的模組加入到nginx中 / 80 
3.3.3 直接修改makefile檔案 / 84 
3.4 http模組的資料結構 / 85 
3.5 定義自己的http模組 / 88 
3.6 處理使用者請求 / 92 
3.6.1 處理方法的返回值 / 92 
3.6.2 獲取uri和引數 / 95 
3.6.3 獲取http頭部 / 98 
3.6.4 獲取http包體 / 101 
3.7 傳送響應 / 102 
3.7.1 傳送http頭部 / 102 
3.7.2 將記憶體中的字串作為包體傳送 / 104 
3.7.3 經典的“hello world”示例 / 106 
3.8 將磁碟檔案作為包體傳送 / 107 
3.8.1 如何傳送磁碟中的檔案 / 107 
3.8.2 清理檔案控制代碼 / 110 
3.8.3 支援使用者多執行緒下載和斷點續傳 / 111 
3.9 用c++語言編寫http模組 / 112 
3.9.1 編譯方式的修改 / 112 
3.9.2 程式中的符號轉換 / 114 
3.10 小結 / 114 
第4章 配置、error日誌和請求上下文 / 115 
4.1 http配置項的使用場景 / 115 
4.2 怎樣使用http配置 / 117 
4.2.1 分配用於儲存配置引數的資料結構 / 117 
4.2.2 設定配置項的解析方式 / 119 
4.2.3 使用14種預設方法解析配置項 / 125 
4.2.4 自定義配置項處理方法 / 136 
4.2.5 合併配置項 / 137 
4.3 http配置模型 / 140 
4.3.1 解析http配置的流程 / 141 
4.3.2 http配置模型的記憶體佈局 / 144 
4.3.3 如何合併配置項 / 147 
4.3.4 預設配置項處理方法的工作原理 / 149 
4.4 error日誌的用法 / 150 
4.5 請求的上下文 / 155 
4.5.1 上下文與全非同步web伺服器的關係 / 155 
4.5.2 如何使用http上下文 / 156 
4.5.3 http框架如何維護上下文結構 / 157 
4.6 小結 / 158 
第5章 訪問第三方服務 / 159 
5.1 upstream的使用方式 / 160 
5.1.1 ngx_http_upstream_t結構體 / 163 
5.1.2 設定upstream的限制性引數 / 164 
5.1.3 設定需要訪問的第三方伺服器地址 / 165 
5.1.4 設定回撥方法 / 166 
5.1.5 如何啟動upstream機制 / 166 
5.2 回撥方法的執行場景 / 167 
5.2.1 create_request回撥方法 / 167 
5.2.2 reinit_request回撥方法 / 169 
5.2.3 finalize_request回撥方法 / 170 
5.2.4 process_header回撥方法 / 171 
5.2.5 rewrite_redirect回撥方法 / 172 
5.2.6 input_filter_init與input_filter回撥方法 / 172 
5.3 使用upstream的示例 / 173 
5.3.1 upstream的各種配置引數 / 174 
5.3.2 請求上下文 / 175 
5.3.3 在create_request方法中構造請求 / 176 
5.3.4 在process_header方法中解析包頭 / 177 
5.3.5 在finalize_request方法中釋放資源 / 180 
5.3.6 在ngx_http_mytest_handler方法中啟動upstream / 181 
5.4 subrequest的使用方式 / 183 
5.4.1 配置子請求的處理方式 / 183 
5.4.2 實現子請求處理完畢時的回撥方法 / 184 
5.4.3 處理父請求被重新啟用後的回撥方法 / 185 
5.4.4 啟動subrequest子請求 / 185 
5.5 subrequest執行過程中的主要場景 / 186 
5.5.1 如何啟動subrequest / 186 
5.5.2 如何轉發多個子請求的響應包體 / 188 
5.5.3 子請求如何啟用父請求 / 192 
5.6 subrequest使用的例子 / 193 
5.6.1 配置檔案中子請求的設定 / 194 
5.6.2 請求上下文 / 194 
5.6.3 子請求結束時的處理方法 / 195 
5.6.4 父請求的回撥方法 / 196 
5.6.5 啟動subrequest / 197 
5.7 小結 / 198 
第6章 開發一個簡單的http過濾模組 / 199 
6.1 過濾模組的意義 / 199 
6.2 過濾模組的呼叫順序 / 200 
6.2.1 過濾連結串列是如何構成的 / 200 
6.2.2 過濾連結串列的順序 / 203 
6.2.3 官方預設http過濾模組的功能簡介 / 204 
6.3 http過濾模組的開發步驟 / 206 
6.4 http過濾模組的簡單例子 / 207 
6.4.1 如何編寫config檔案 / 208 
6.4.2 配置項和上下文 / 208 
6.4.3 定義http過濾模組 / 210 
6.4.4 初始化http過濾模組 / 211 
6.4.5 處理請求中的http頭部 / 212 
6.4.6 處理請求中的http包體 / 213 
6.5 小結 / 214 
第7章 nginx提供的高階資料結構 / 215 
7.1 nginx提供的高階資料結構概述 / 215 
7.2 ngx_queue_t雙向連結串列 / 217 
7.2.1 為什麼設計ngx_queue_t雙向連結串列 / 217 
7.2.2 雙向連結串列的使用方法 / 217 
7.2.3 使用雙向連結串列排序的例子 / 219 
7.2.4 雙向連結串列是如何實現的 / 221 
7.3 ngx_array_t動態陣列 / 222 
7.3.1 為什麼設計ngx_array_t動態陣列 / 223 
7.3.2 動態陣列的使用方法 / 223 
7.3.3  使用動態陣列的例子 / 225 
7.3.4 動態陣列的擴容方式 / 226 
7.4 ngx_list_t單向連結串列 / 226 
7.5 ngx_rbtree_t紅黑樹 / 227 
7.5.1 為什麼設計ngx_rbtree_t紅黑樹 / 227 
7.5.2 紅黑樹的特性 / 228 
7.5.3 紅黑樹的使用方法 / 230 
7.5.4 使用紅黑樹的簡單例子 / 233 
7.5.5 如何自定義新增成員方法 / 234 
7.6 ngx_radix_tree_t基數樹 / 236 
7.6.1 ngx_radix_tree_t基數樹的原理 / 236 
7.6.2 基數樹的使用方法 / 238 
7.6.3 使用基數樹的例子 / 239 
7.7 支援萬用字元的散列表 / 240 
7.7.1 ngx_hash_t基本散列表 / 240 
7.7.2 支援萬用字元的散列表 / 243 
7.7.3 帶萬用字元散列表的使用例子 / 250 
7.8 小結 / 254 
第三部分 深入nginx 
第8章 nginx基礎架構 / 256 
8.1 web伺服器設計中的關鍵約束 / 256 
8.2 nginx的架構設計 / 259 
8.2.1 優秀的模組化設計 / 259 
8.2.2 事件驅動架構 / 263 
8.2.3 請求的多階段非同步處理 / 264 
8.2.4 管理程序、多工作程序設計 / 267 
8.2.5 平臺無關的程式碼實現 / 268 
8.2.6 記憶體池的設計 / 268 
8.2.7 使用統一管道過濾器模式的http過濾模組 / 268 
8.2.8 其他一些使用者模組 / 269 
8.3 nginx框架中的核心結構體ngx_cycle_t / 269 
8.3.1 ngx_listening_t結構體 / 269 
8.3.2 ngx_cycle_t結構體 / 271 
8.3.3 ngx_cycle_t支援的方法 / 273 
8.4 nginx啟動時框架的處理流程 / 275 
8.5 worker程序是如何工作的 / 278 
8.6 master程序是如何工作的 / 281 
8.7 小結 / 286 
第9章 事件模組 / 287 
9.1 事件處理框架概述 / 287 
9.2 nginx事件的定義 / 290 
9.3 nginx連線的定義 / 293 
9.3.1 被動連線 / 294 
9.3.2 主動連線 / 297 
9.3.3 ngx_connection_t連線池 / 298 
9.4 ngx_events_module核心模組 / 300 
9.4.1 如何管理所有事件模組的配置項 / 301 
9.4.2 管理事件模組 / 303 
9.5 ngx_event_core_module事件模組 / 305 
9.6 epoll事件驅動模組 / 310 
9.6.1 epoll的原理和用法 / 311 
9.6.2 如何使用epoll / 313 
9.6.3 ngx_epoll_module模組的實現 / 315 
9.7 定時器事件 / 323 
9.7.1 快取時間的管理 / 324 
9.7.2 快取時間的精度 / 326 
9.7.3 定時器的實現 / 327 
9.8 事件驅動框架的處理流程 / 328 
9.8.1 如何建立新連線 / 329 
9.8.2 如何解決“驚群”問題 / 330 
9.8.3 如何實現負載均衡 / 333 
9.8.4 post事件佇列 / 334 
9.8.5 ngx_process_events_and_timers流程 / 335 
9.9 檔案的非同步i/o / 338 
9.9.1 linux核心提供的檔案非同步i/o / 339 
9.9.2 ngx_epoll_module模組中實現的針對檔案的非同步i/o / 342 
9.10 小結 / 346 
第10章 http框架的初始化 / 347 
10.1 http框架概述 / 348 
10.2 管理http模組的配置項 / 351 
10.2.1 管理main級別下的配置項 / 352 
10.2.2 管理server級別下的配置項 / 354 
10.2.3 管理location級別下的配置項 / 357 
10.2.4 不同級別配置項的合併 / 362 
10.3 監聽埠的管理 / 367 
10.4 server的快速檢索 / 369 
10.5 location的快速檢索 / 371 
10.6 http請求的11個處理階段 / 372 
10.6.1 http處理階段的普適規則 / 374 
10.6.2 ngx_http_post_read_phase階段 / 376 
10.6.3 ngx_http_server_rewrite_phase階段 / 378 
10.6.4 ngx_http_find_config_phase階段 / 379 
10.6.5 ngx_http_rewrite_phase階段 / 379 
10.6.6 ngx_http_post_rewrite_phase階段 / 379 
10.6.7 ngx_http_preaccess_phase階段 / 379 
10.6.8 ngx_http_access_phase階段 / 380 
10.6.9 ngx_http_post_access_phase階段 / 380 
10.6.10 ngx_http_try_files_phase階段 / 381 
10.6.11 ngx_http_content_phase階段 / 381 
10.6.12 ngx_http_log_phase階段 / 382 
10.7 http框架的初始化流程 / 383 
10.8 小結 / 385 
第11章 http框架的執行流程 / 386 
11.1 http框架執行流程概述 / 387 
11.2 新連線建立時的行為 / 388 
11.3 第一次可讀事件的處理 / 390 
11.4 接收http請求行 / 396 
11.5 接收http頭部 / 399 
11.6 處理http請求 / 403 
11.6.1 ngx_http_core_generic_phase / 409 
11.6.2 ngx_http_core_rewrite_phase / 411 
11.6.3 ngx_http_core_access_phase / 412 
11.6.4 ngx_http_core_content_phase / 415 
11.7 subrequest與post請求 / 419 
11.8 處理http包體 / 421 
11.8.1 接收包體 / 422 
11.8.2 放棄接收包體 / 429 
11.9 傳送http響應 / 433 
11.9.1 ngx_http_send_header / 434 
11.9.2 ngx_http_output_filter / 436 
11.9.3 ngx_http_writer / 440 
11.10 結束http請求 / 442 
11.10.1 ngx_http_close_connection / 443 
11.10.2 ngx_http_free_request / 444 
11.10.3 ngx_http_close_request / 446 
11.10.4 ngx_http_finalize_connection / 447 
11.10.5 ngx_http_terminate_request / 447 
11.10.6 ngx_http_finalize_request / 448 
11.11 小結 / 452 
第12章 upstream機制的設計與實現 / 453 
12.1 upstream機制概述 / 453 
12.1.1 設計目的 / 454 
12.1.2 ngx_http_upstream_t資料結構的意義 / 456 
12.1.3 ngx_http_upstream_conf_t配置結構體 / 459 
12.2 啟動upstream / 462 
12.3 與上游伺服器建立連線 / 464 
12.4 傳送請求到上游伺服器 / 467 
12.5 接收上游伺服器的響應頭部 / 470 
12.5.1 應用層協議的兩段劃分方式 / 470 
12.5.2 處理包體的3種方式 / 471 
12.5.3 接收響應頭部的流程 / 473 
12.6 不轉發響應時的處理流程 / 476 
12.6.1 input_filter方法的設計 / 477 
12.6.2 預設的input_filter方法 / 478 
12.6.3 接收包體的流程 / 479 
12.7 以下游網速優先來轉發響應 / 481 
12.7.1 轉發響應的包頭 / 482 
12.7.2 轉發響應的包體 / 484 
12.8 以上游網速優先來轉發響應 / 489 
12.8.1 ngx_event_pipe_t結構體的意義 / 489 
12.8.2 轉發響應的包頭 / 493 
12.8.3 轉發響應的包體 / 495 
12.8.4 ngx_event_pipe_read_upstream方法 / 498 
12.8.5 ngx_event_pipe_write_to_downstream方法 / 502 
12.9 結束upstream請求 / 504 
12.10 小結 / 508 
第13章 郵件代理模組 / 509 
13.1 郵件代理伺服器的功能 / 509 
13.2 郵件模組的處理框架 / 512 
13.2.1 一個請求的8個獨立處理階段 / 512 
13.2.2 郵件類模組的定義 / 514 
13.2.3 郵件框架的初始化 / 516 
13.3 初始化請求 / 517 
13.3.1 描述郵件請求的ngx_mail_session_t結構體 / 517 
13.3.2 初始化郵件請求的流程 / 519 
13.4 接收並解析客戶端請求 / 520 
13.5 郵件認證 / 520 
13.5.1 ngx_mail_auth_http_ctx_t結構體 / 520 
13.5.2 與認證伺服器建立連線 / 522 
13.5.3 傳送請求到認證伺服器 / 522 
13.5.4 接收並解析響應 / 525 
13.6 與上游郵件伺服器間的認證互動 / 526 
13.6.1 ngx_mail_proxy_ctx_t結構體 / 526 
13.6.2 向上遊郵件伺服器發起連線 / 527 
13.6.3 與郵件伺服器認證互動的過程 / 528 
13.7 透傳上游郵件伺服器與客戶端間的流 / 530 
13.8 小結 / 535 
第14章 程序間的通訊機制 / 536 
14.1 概述 / 536 
14.2 共享記憶體 / 536 
14.3 原子操作 / 541 
14.3.1 不支援原子庫下的原子操作 / 541 
14.3.2 x86架構下的原子操作 / 542 
14.3.3 自旋鎖 / 545 
14.4 nginx頻道 / 546 
14.5 訊號 / 549 
14.6 訊號量 / 551 
14.7 檔案鎖 / 553 
14.8 互斥鎖 / 556 
14.8.1 檔案鎖實現的ngx_shmtx_t鎖 / 558 
14.8.2 原子變數實現的ngx_shmtx_t鎖 / 560 
14.9 小結 / 565 


前言

  為什麼要寫這本書 
  當我試圖在產品的關鍵位置設計一個高效能Web伺服器時,我選擇使用成熟的Nginx。選擇它的理由為:首先,它對伺服器效能上的挖掘已經達到了很高水平,它能儘量使不同的硬體(包括網絡卡、硬碟、不同的CPU核心)併發執行,同時軟體中又沒有阻塞程序使之睡眠的程式碼,從效能上來說,它可以挑戰任何伺服器。其次,完全基於事件驅動的伺服器開發效率往往很不理想,它們要處理的事件過於底層化、細節化,這使得各功能模組無法聚焦於業務,最終產品的功能都較為單一,不會有豐富的可選功能。但Nginx卻不然,由於它在軟體架構上具有優秀的設計,使得Nginx完全由許多簡單的模組構成,各模組(特別是HTTP模組)不用介入底層細節,在盡享分階段、無阻塞的事件驅動架構下,可以專注於業務功能的實現,這樣最終為Nginx帶來了大量的官方、第三方的功能模組,使得功能同樣強大的Nginx在產品核心位置上足以擔當重任,經受住海量請求的考驗。 
  當Nginx已有模組提供的功能不能完全實現我的所有業務需求時,我可以在Nginx的後端再搭建一個實現了缺失功能的非Nginx伺服器,將Nginx無法實現的請求反向代理到這臺伺服器上處理。但這樣也有一定的弊端,首先增大了處理請求的開銷,其次後端伺服器的設計仍然制約著總體效能(它依然需要解決Nginx解決過的無阻塞問題,那樣才能像Nginx一樣高效),這樣做僅適用於對效能要求不高的場景。唯有開發一個實現了所需功能的自定義Nginx模組嵌入到Nginx程式碼中,才能讓自己的業務像Nginx一樣充分挖掘伺服器的硬體資源,及時地響應百萬級別的併發TCP連線。 
  當我在開發Nginx模組之前,試圖在市面上找到一本關於Nginx模組開發的書籍(無論是中文還是英文)時卻一無所獲。我只能找到如何使用Nginx及其已有模組的書籍。為了開發Nginx模組,我只能通過閱讀Nginx極度缺少註釋的原始碼,並分析各種官方Nginx模組來逐步還原其設計思想,反覆嘗試、驗證著怎樣的模組能夠使用Nginx的基礎架構,和豐富的跨平臺工具方法,同時符合Nginx設計思想,使Nginx擁有媲美Linux核心的一流效率。這個過程耗費了我很多的精力,因此,我希望今後的Nginx使用者、開發者在遇到同樣的問題時,不至於還要很痛苦地閱讀原始碼來找到模組開發方法,而是簡單地按照章節查閱本書,就可以快速找到怎樣簡單、高效地開發Nginx模組,把精力放在業務的實現上。這是我寫這本書的第一個目的。 
  當我們產品中執行的Nginx出現了問題時,往往是通過找到錯誤的配置項、使用方式來解決的,這樣也的確能夠修復大部分問題。但是更深層次的問題,或者是使用場景比較偏僻,抑或是Nginx自身程式碼考慮得不夠全面時,這些問題往往只能由那些花費大量精力研究Nginx原始碼的工程師來解決。我寫作本書的第二個目的是希望通過透徹地解析Nginx架構,幫助讀者深入理解Nginx,既能夠正確地使用它,也能在它出現任何問題時找到根本原因,進而用最合適的方法修復或者回避問題。 
  Nginx是一個優秀的事件驅動框架,雖然它在HTTP的處理上非常出色,但它絕不僅僅用於Web伺服器。Nginx非常適合開發在傳輸層以TCP對外提供服務的伺服器程式。基於Nginx框架開發程式有5個優勢: 
  1)Nginx將網路、磁碟及定時器等非同步事件的驅動都做了非常好的封裝,基於它開發將可以忽略這些事件處理的細節。 
  2)Nginx封裝了許多平臺無關的介面、容器,適用於跨平臺開發。 
  3)優秀的模組化設計,使得開發者可以輕易地複用各種已有的模組,其中既包括基本的讀取配置、記錄日誌等模組,也包括處理請求的諸如HTTP、mail等高階功能模組。 
  4)Nginx是作為伺服器來設計其框架的,因此,它在伺服器程序的管理上相當出色,基於它開發伺服器程式可以輕鬆地實現程式的動態升級,子程序的監控、管理,配置項的動態修改生效等。 
  5)Nginx充分考慮到各作業系統所擅長的“絕活”,能夠使用特殊的系統呼叫更高效地完成任務時,絕不會去使用低效的通用介面。尤其對於Linux作業系統,Nginx不遺餘力地做了大量優化。 
  當我們期望編寫一款能夠以低負載處理高併發請求並且主要處理基於TCP的伺服器程式時,推薦選擇Nginx,它可能會帶給我們意外的驚喜。這本書的第三部分,將通過分析Nginx的內部架構,幫助讀者瞭解怎樣基於Nginx開發高效的TCP伺服器程式:通過開發一種新的模組型別,實現一種新的功能框架來提供極佳的擴充套件性,使得功能子模組僅關注於業務的開發,忽視底層事件的處理。這是我寫作本書的第三個目的。 
  除了這3個主要目的外,我還希望通過這本書向大家展示Nginx在伺服器開發上的許多巧妙設計,它們或在抽象設計上精妙,或通過作業系統精確、節省地使用硬體資源,這些細節之處的設計都體現了Igor Sysoev的不凡功底。即使我們完全不使用Nginx,學習這些技巧也將有助於我們伺服器程式設計水平的提升。 
  讀者物件 
  本書適合以下讀者閱讀。 
  對Nginx及如何將它搭建成一個高效能的Web伺服器感興趣的讀者。 
  希望通過開發特定的HTTP模組實現高效能Web伺服器的讀者。 
  希望瞭解Nginx的架構設計,學習怎樣充分使用伺服器上的硬體資源的讀者。 
  瞭解如何快速定位、修復Nginx中深層次Bug的讀者。 
  希望利用Nginx提供的框架,設計出任何基於TCP的、無阻塞的、易於擴充套件的伺服器的讀者。 
.  背景知識 
  如果僅希望瞭解怎樣使用已有的Nginx功能搭建伺服器,那麼閱讀本書不需要什麼先決條件。但如果希望通過閱讀本書的第二、第三部分,來學習Nginx的模組開發和架構設計技巧,則必須瞭解C語言的基本語法。在閱讀本書第三部分時,需要讀者對TCP有一個基本的瞭解,同時對Linux作業系統也應該有簡單的瞭解。 
  如何閱讀本書 
  我很希望將本書寫成一本“step by step”式(循序漸進式)的書籍,因為這樣最能節省讀者的時間,然而,由於3個主要寫作目的想解決的問題都不是那麼簡單,所以這本書只能做一個折中的處理。 
  在第一部分的前兩章中,將只探討如何使用Nginx這一問題。閱讀這一部分的讀者不需要了解C語言,就可以學習如何部署Nginx,學習如何向其中新增各種官方、第三方的功能模組,如何通過修改配置檔案來更改Nginx及各模組的功能,如何修改Linux作業系統上的引數來優化伺服器效能,最終向用戶提供企業級的Web伺服器。這一部分介紹配置項的方式,更偏重於帶領對Nginx還比較陌生的讀者熟悉它,通過了解幾個基本Nginx模組的配置修改方式,進而使讀者可以通過查詢官網、第三方網站來了解如何使用所有Nginx模組的用法。 
  在第二部分的第3章~第7章中,都是以例子來介紹HTTP模組的開發方式的,這裡有些接近於“step by step”的學習方式,我在寫作這一部分時,會通過循序漸進的方式使讀者能夠快速上手,同時會穿插著介紹其常見用法的基本原理。 
  在第三部分,將開始介紹Nginx的完整框架,閱讀到這裡時將會了解第二部分中HTTP模組為何以此種方式開發,同時將可以輕易地開發出Nginx模組。這一部分並不僅僅滿足於闡述Nginx架構,而是會探討其為何如此設計,只有這樣才能拋開HTTP框架、郵件代理框架,實現一種新的業務框架、一種新的模組型別。 
  對於Nginx的使用還不熟悉的讀者應當從第1章開始學習,前兩章將幫助你快速瞭解Nginx。 
  使用過Nginx,但對如何開發Nginx的HTTP模組不太瞭解的讀者可以直接從第3章開始學習,在這一章閱讀完後,即可編寫一個功能大致完整的HTTP模組。然而,編寫企業級的模組必須閱讀完第4章才能做到,這一章將會介紹編寫產品線上伺服器程式時必備的3個手段。第5章舉例說明了兩種編寫複雜HTTP模組的方式,在第三部分會對這兩種方式有進一步的說明。第6章介紹一種特殊的HTTP模組—HTTP過濾模組的編寫方法。第7章探討基礎容器的用法,這同樣是複雜模組的必備工具。 
  如果讀者對於普通HTTP模組的編寫已經很熟悉,想深入地實現更為複雜的HTTP模組,或者想了解郵件代理伺服器的設計與實現,或者希望編寫一種新的處理其他協議的模組,或者僅僅想了解Nginx的架構設計,都可以直接從第8章開始學習,這一章會從整體上系統介紹Nginx的模組式設計。第9章的事件框架是Nginx處理TCP的基礎,這一章無法跳過。閱讀第8、第9章時可能會遇到許多第7章介紹過的容器,這時可以回到第7章查詢其用法和意義。第10章~第12章介紹HTTP框架,通過這3章的學習會對HTTP模組的開發有深入的瞭解,同時可以學習HTTP框架的優秀設計。第13章簡單地介紹了郵件代理伺服器的設計,它近似於簡化版的HTTP框架。第14章介紹了程序間同步的工具。 
  為了不讓讀者陷入程式碼的“汪洋大海”中,在本書中大量使用了圖表,這樣可以使讀者快速、大體地瞭解流程和原理。關鍵地方會直接給出程式碼,並添加註釋加以說明。希望這種方式能夠幫助讀者減少閱讀花費的時間,更快、更好地把握Nginx,同時深入到細節中。 
  在本書開始寫作時,由於Nginx的最新穩定版本是1.0.14,所以本書是基於此版本來編寫的。截止到本書編寫完成時,Nginx的穩定版本已經上升到了1.2.4。但這不會對本書的閱讀造成困擾,因為本書主要是在介紹Nginx的基本框架程式碼,以及怎樣使用這些框架程式碼開發新的Nginx模組,而不是介紹Nginx的某些功能。在這些基本框架程式碼中,Nginx一般不會做任何改變,否則已有的大量Nginx模組將無法工作,這種損失也是不可承受的。而且,Nginx框架為具體的功能模組提供了足夠的靈活性,修改功能時很少需要修改框架程式碼。 
  Nginx是跨平臺的伺服器,然而這本書將只針對最常見的Linux作業系統進行分析,這樣做一方面是篇幅所限,另一方面則是本書的寫作目的主要在於告訴讀者如何基於Nginx編寫程式碼,而不是怎樣在一個具體的作業系統上修改配置來使用Nginx。因此,即使本書以Linux系統為代表講述Nginx,也不會影響使用其他作業系統的讀者閱讀,因為作業系統的差別對閱讀本書的影響實在是非常小。 
  勘誤和支援 
  由於作者的水平有限,加之編寫的時間也很倉促,書中難免會出現一些錯誤或者不準確的地方,懇請讀者批評指正。為此,我特意建立了一個線上支援與應急方案的二級站點:
http://nginx.weebly.com
。讀者可以將書中的錯誤釋出在Bug勘誤表頁面中,同時如果你遇到任何問題,也可以訪問Q&A頁面,我將盡量在線上為讀者提供最滿意的解答。書中的全部原始檔都將釋出在這個網站上,我也會將相應的功能更新及時釋出出來。如果你有更多的寶貴意見,也歡迎你傳送郵件至我的郵箱[email protected],期待能夠聽到讀者的真摯反饋。 
  致謝 
  我首先要感謝Igor Sysoev,他在Nginx設計上展現的功力令人折服,正是他的工作成果才讓本書的誕生有了意義。 
  lisa是機械工業出版社華章公司的優秀編輯,非常值得信任。在這半年的寫作過程中,她花費了很多時間、精力來閱讀我的書稿,指出了許多文字和格式上的錯誤,她提出的建議大大提高了本書的可讀性。 
  在這半年時間內,一邊工作一邊寫作給我帶來了很大的壓力,所以我要感謝我的父母在生活上對我無微不至的照顧,使我可以全力投入到寫作中。繁忙的工作之餘,寫作又佔用了休息時間的絕大部分,感謝我的太太對我的體諒和鼓勵,讓我始終以高昂的鬥志投入到本書的寫作中。 
  感謝我工作中的同事們,正是在與他們一起工作的日子裡,我才不斷地對技術有新的感悟;正是那些充滿激情的歲月,才使得我越來越熱愛伺服器技術的開發。 
  謹以此書,獻給我最親愛的家人,以及眾多熱愛Nginx的朋友。 
  陶輝