深入理解Nginx:模組開發與架構解析(第2版)

CiCi島發表於2018-12-04

網站

更多書籍點選進入>> CiCi島

下載

電子版僅供預覽及學習交流使用,下載後請24小時內刪除,支援正版,喜歡的請購買正版書籍

封頁

封頁

內容簡介

本書包括四大部分:Nginx能幫我做什麼;如何編寫一個定製的httpmodule;深入Nginx;實戰。第一部分針對初級讀者,介紹Nginx關於獲取編譯執行的基本知識。第二部分針對中級讀者,以一個例子為主線,告訴讀者如何開發一個http模組,這部分讀者不需要深入瞭解Nginx的細節,只需要知道如何實現一個基本的http模組。第三部分針對高階讀者,這是本書的重點,徹底解析Nginx架構,深入探討Nginx各種設計的目的與意義,並對第二部分使用到的一些特性進行程式碼設計實現上的探索。讀者讀完本部分,會對整個Nginx架構有清晰的認識,可以編寫各種模組(不侷限於http模組)插入到Nginx中,從而定製自己的Nginx。第四部分針對中高階讀者,以Tengine的開源模組為例,幫助讀者從實戰角度理解第二、三部分描述的內容。

目 錄

Contents?目  錄

前 言

第一部分 Nginx能幫我們做什麼

1章 研究Nginx前的準備工作 2

1.1
 Nginx是什麼 2

1.2
 為什麼選擇Nginx 5

1.3
 準備工作 7

1.3.1
 Linux作業系統 7

1.3.2
 使用Nginx的必備軟體 7

1.3.3
 磁碟目錄 8

1.3.4
 Linux核心引數的優化 9

1.3.5
 獲取Nginx原始碼 10

1.4
 編譯安裝Nginx 11

1.5
 conf?igure詳解 11

1.5.1
 conf?igure的命令引數 11

1.5.2
 conf?igure執行流程 18

1.5.3
 conf?igure生成的檔案 21

1.6
 Nginx的命令列控制 23

1.7
 小結 27

2章 Nginx的配置 28

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
 優化效能的配置項 37

2.3.4
 事件類配置項 39

2.4
 用HTTP核心模組配置一個靜態Web伺服器 40

2.4.1
 虛擬主機與請求的分發 41

2.4.2
 檔案路徑的定義 45

2.4.3
 記憶體及磁碟資源的分配 47

2.4.4
 網路連線的設定 49

2.4.5
 MIME型別的設定 52

2.4.6
 對客戶端請求的限制 53

2.4.7
 檔案操作的優化 54

2.4.8
 對客戶端請求的特殊處理 56

2.4.9
 ngx_http_core_module模組提供的變數 57

2.5
 用HTTP proxy module配置一個反向代理伺服器 59

2.5.1
 負載均衡的基本配置 61

2.5.2
 反向代理的基本配置 63

2.6
 小結 66

第二部分 如何編寫HTTP模組

3章 開發一個簡單的HTTP模組 68

3.1
 如何呼叫HTTP模組 68

3.2
 準備工作 70

3.2.1
 整型的封裝 71

3.2.2
 ngx_str_t資料結構 71

3.2.3
 ngx_list_t資料結構 71

3.2.4
 ngx_table_elt_t資料結構 75

3.2.5
 ngx_buf_t資料結構 75

3.2.6
 ngx_chain_t資料結構 77

3.3
 如何將自己的HTTP模組編譯進Nginx 77

3.3.1
 conf?ig檔案的寫法 77

3.3.2
 利用conf?igure指令碼將定製的模組加入到Nginx 78

3.3.3
 直接修改Makef?ile檔案 81

3.4
 HTTP模組的資料結構 82

3.5
 定義自己的HTTP模組 86

3.6
 處理使用者請求 89

3.6.1
 處理方法的返回值 89

3.6.2
 獲取URI和引數 92

3.6.3
 獲取HTTP頭部 94

3.6.4
 獲取HTTP包體 97

3.7
 傳送響應 99

3.7.1
 傳送HTTP頭部 99

3.7.2
 將記憶體中的字串作為包體傳送 101

3.7.3
 經典的“Hello World”示例 102

3.8
 將磁碟檔案作為包體傳送 103

3.8.1
 如何傳送磁碟中的檔案 104

3.8.2
 清理檔案控制程式碼 106

3.8.3
 支援使用者多執行緒下載和斷點續傳 107

3.9
 用C 語言編寫HTTP模組 108

3.9.1
 編譯方式的修改 108

3.9.2
 程式中的符號轉換 109

3.10
 小結 110

4章 配置、error日誌和請求上下文 111

4.1
 http配置項的使用場景 111

4.2
 怎樣使用http配置 113

4.2.1
 分配用於儲存配置引數的資料結構 113

4.2.2
 設定配置項的解析方式 115

4.2.3
 使用14種預設方法解析配置項 121

4.2.4
 自定義配置項處理方法 131

4.2.5
 合併配置項 133

4.3
 HTTP配置模型 135

4.3.1
 解析HTTP配置的流程 136

4.3.2
 HTTP配置模型的記憶體佈局 139

4.3.3
 如何合併配置項 142

4.3.4
 預設配置項處理方法的工作原理 144

4.4
 error日誌的用法 145

4.5
 請求的上下文 149

4.5.1
 上下文與全非同步Web伺服器的關係 149

4.5.2
 如何使用HTTP上下文 151

4.5.3
 HTTP框架如何維護上下文結構 152

4.6
 小結 153

5章 訪問第三方服務 154

5.1
 upstream的使用方式 155

5.1.1
 ngx_http_upstream_t結構體 158

5.1.2
 設定upstream的限制性引數 159

5.1.3
 設定需要訪問的第三方伺服器地址 160

5.1.4
 設定回撥方法 161

5.1.5
 如何啟動upstream機制 161

5.2
 回撥方法的執行場景 162

5.2.1
 create_request回撥方法 162

5.2.2
 reinit_request回撥方法 164

5.2.3
 f?inalize_request回撥方法 165

5.2.4
 process_header回撥方法 165

5.2.5
 rewrite_redirect回撥方法 167

5.2.6
 input_f?ilter_initinput_f?ilter回撥方法 167

5.3
 使用upstream的示例 168

5.3.1
 upstream的各種配置引數 168

5.3.2
 請求上下文 170

5.3.3
 在create_request方法中構造請求 170

5.3.4
 在process_header方法中解析包頭 171

5.3.5
 在f?inalize_request方法中釋放資源 175

5.3.6
 在ngx_http_mytest_handler方法中啟動upstream 175

5.4
 subrequest的使用方式 177

5.4.1
 配置子請求的處理方式 177

5.4.2
 實現子請求處理完畢時的回撥方法 178

5.4.3
 處理父請求被重新啟用後的回撥方法 179

5.4.4
 啟動subrequest子請求 179

5.5
 subrequest執行過程中的主要場景 180

5.5.1
 如何啟動subrequest 180

5.5.2
 如何轉發多個子請求的響應包體 182

5.5.3
 子請求如何啟用父請求 185

5.6
 subrequest使用的例子 187

5.6.1
 配置檔案中子請求的設定 187

5.6.2
 請求上下文 188

5.6.3
 子請求結束時的處理方法 188

5.6.4
 父請求的回撥方法 189

5.6.5
 啟動subrequest 190

5.7
 小結 191

6章 開發一個簡單的HTTP過濾模組 192

6.1
 過濾模組的意義 192

6.2
 過濾模組的呼叫順序 193

6.2.1
 過濾連結串列是如何構成的 194

6.2.2
 過濾連結串列的順序 196

6.2.3
 官方預設HTTP過濾模組的功能簡介 197

6.3
 HTTP過濾模組的開發步驟 198

6.4
 HTTP過濾模組的簡單例子 200

6.4.1
 如何編寫conf?ig檔案 201

6.4.2
 配置項和上下文 201

6.4.3
 定義HTTP過濾模組 203

6.4.4
 初始化HTTP過濾模組 204

6.4.5
 處理請求中的HTTP頭部 204

6.4.6
 處理請求中的HTTP包體 206

6.5
 小結 206

7章 Nginx提供的高階資料結構 207

7.1
 Nginx提供的高階資料結構概述 207

7.2
 ngx_queue_t雙向連結串列 209

7.2.1
 為什麼設計ngx_queue_t雙向連結串列 209

7.2.2
 雙向連結串列的使用方法 209

7.2.3
 使用雙向連結串列排序的例子 212

7.2.4
 雙向連結串列是如何實現的 213

7.3
 ngx_array_t動態陣列 215

7.3.1
 為什麼設計ngx_array_t動態陣列 215

7.3.2
 動態陣列的使用方法 215

7.3.3
  使用動態陣列的例子 217

7.3.4
 動態陣列的擴容方式 218

7.4
 ngx_list_t單向連結串列 219

7.5
 ngx_rbtree_t紅黑樹 219

7.5.1
 為什麼設計ngx_rbtree_t紅黑樹 219

7.5.2
 紅黑樹的特性 220

7.5.3
 紅黑樹的使用方法 222

7.5.4
 使用紅黑樹的簡單例子 225

7.5.5
 如何自定義新增成員方法 226

7.6
 ngx_radix_tree_t基數樹 228

7.6.1
 ngx_radix_tree_t基數樹的原理 228

7.6.2
 基數樹的使用方法 230

7.6.3
 使用基數樹的例子 231

7.7
 支援萬用字元的雜湊表 232

7.7.1
 ngx_hash_t基本雜湊表 232

7.7.2
 支援萬用字元的雜湊表 235

7.7.3
 帶萬用字元雜湊表的使用例子 241

7.8
 小結 245

第三部分 深入Nginx

8章 Nginx基礎架構 248

8.1
 Web伺服器設計中的關鍵約束 249

8.2
 Nginx的架構設計 251

8.2.1
 優秀的模組化設計 251

8.2.2
 事件驅動架構 254

8.2.3
 請求的多階段非同步處理 256

8.2.4
 管理程式、多工作程式設計 259

8.2.5
 平臺無關的程式碼實現 259

8.2.6
 記憶體池的設計 259

8.2.7
 使用統一管道過濾器模式的HTTP過濾模組 260

8.2.8
 其他一些使用者模組 260

8.3
 Nginx框架中的核心結構體ngx_cycle_t 260

8.3.1
 ngx_listening_t結構體 261

8.3.2
 ngx_cycle_t結構體 262

8.3.3
 ngx_cycle_t支援的方法 264

8.4
 Nginx啟動時框架的處理流程 266

8.5
 worker程式是如何工作的 269

8.6
 master程式是如何工作的 271

8.7
 ngx_pool_t記憶體池 276

8.8
 小結 284

9章 事件模組 285

9.1
 事件處理框架概述 286

9.2
 Nginx事件的定義 288

9.3
 Nginx連線的定義 291

9.3.1
 被動連線 292

9.3.2
 主動連線 295

9.3.3
 ngx_connection_t連線池 296

9.4
 ngx_events_module核心模組 297

9.4.1
 如何管理所有事件模組的配置項 299

9.4.2
 管理事件模組 300

9.5
 ngx_event_core_module事件模組 302

9.6
 epoll事件驅動模組 308

9.6.1
 epoll的原理和用法 308

9.6.2
 如何使用epoll 310

9.6.3
 ngx_epoll_module模組的實現 312

9.7
 定時器事件 320

9.7.1
 快取時間的管理 320

9.7.2
 快取時間的精度 323

9.7.3
 定時器的實現 323

9.8
 事件驅動框架的處理流程 324

9.8.1
 如何建立新連線 325

9.8.2
 如何解決“驚群”問題 327

9.8.3
 如何實現負載均衡 329

9.8.4
 post事件佇列 330

9.8.5
 ngx_process_events_and_timers流程 331

9.9
 檔案的非同步I/O 334

9.9.1
 Linux核心提供的檔案非同步I/O 335

9.9.2
 ngx_epoll_module模組中實現的針對檔案的非同步I/O 337

9.10
 TCP協議與Nginx 342

9.11
 小結 347

10章 HTTP框架的初始化 348

10.1
 HTTP框架概述 349

10.2
 管理HTTP模組的配置項 352

10.2.1
 管理main級別下的配置項 353

10.2.2
 管理server級別下的配置項 355

10.2.3
 管理location級別下的配置項 358

10.2.4
 不同級別配置項的合併 364

10.3
 監聽埠的管理 367

10.4
 server的快速檢索 370

10.5
 location的快速檢索 370

10.6
 HTTP請求的11個處理階段 372

10.6.1
 HTTP處理階段的普適規則 374

10.6.2
 NGX_HTTP_POST_READ_PHASE階段 375

10.6.3
 NGX_HTTP_SERVER_REWRITE_PHASE階段 378

10.6.4
 NGX_HTTP_FIND_CONFIG_PHASE階段 378

10.6.5
 NGX_HTTP_REWRITE_PHASE階段 378

10.6.6
 NGX_HTTP_POST_REWRITE_PHASE階段 379

10.6.7
 NGX_HTTP_PREACCESS_PHASE階段 379

10.6.8
 NGX_HTTP_ACCESS_PHASE階段 379

10.6.9
 NGX_HTTP_POST_ACCESS_PHASE階段 380

10.6.10
 NGX_HTTP_TRY_FILES_PHASE階段 380

10.6.11
 NGX_HTTP_CONTENT_PHASE階段 380

10.6.12
 NGX_HTTP_LOG_PHASE階段 382

10.7
 HTTP框架的初始化流程 382

10.8
 小結 384

11章 HTTP框架的執行流程 385

11.1
 HTTP框架執行流程概述 386

11.2
 新連線建立時的行為 387

11.3
 第一次可讀事件的處理 388

11.4
 接收HTTP請求行 394

11.5
 接收HTTP頭部 398

11.6
 處理HTTP請求 400

11.6.1
 ngx_http_core_generic_phase 406

11.6.2
 ngx_http_core_rewrite_phase 408

11.6.3
 ngx_http_core_access_phase 409

11.6.4
 ngx_http_core_content_phase 412

11.7
 subrequestpost請求 415

11.8
 處理HTTP包體 417

11.8.1
 接收包體 419

11.8.2
 放棄接收包體 425

11.9
 傳送HTTP響應 429

11.9.1
 ngx_http_send_header 430

11.9.2
 ngx_http_output_f?ilter 432

11.9.3
 ngx_http_writer 435

11.10
 結束HTTP請求 437

11.10.1
 ngx_http_close_connection 438

11.10.2
 ngx_http_free_request 439

11.10.3
 ngx_http_close_request 440

11.10.4
 ngx_http_f?inalize_connection 441

11.10.5
 ngx_http_terminate_request 443

11.10.6
 ngx_http_f?inalize_request 443

11.11
 小結 446

12章 upstream機制的設計與實現 447

12.1
 upstream機制概述 448

12.1.1
 設計目的 448

12.1.2
 ngx_http_upstream_t資料結構的意義 450

12.1.3
 ngx_http_upstream_conf_t配置結構體 453

12.2
 啟動upstream 455

12.3
 與上游伺服器建立連線 457

12.4
 傳送請求到上游伺服器 460

12.5
 接收上游伺服器的響應頭部 463

12.5.1
 應用層協議的兩段劃分方式 463

12.5.2
 處理包體的3種方式 464

12.5.3
 接收響應頭部的流程 465

12.6
 不轉發響應時的處理流程 469

12.6.1
 input_f?ilter方法的設計 469

12.6.2
 預設的input_f?ilter方法 470

12.6.3
 接收包體的流程 472

12.7
 以下游網速優先來轉發響應 473

12.7.1
 轉發響應的包頭 474

12.7.2
 轉發響應的包體 477

12.8
 以上游網速優先來轉發響應 481

12.8.1
 ngx_event_pipe_t結構體的意義 481

12.8.2
 轉發響應的包頭 485

12.8.3
 轉發響應的包體 487

12.8.4
 ngx_event_pipe_read_upstream方法 489

12.8.5
 ngx_event_pipe_write_to_downstream方法 494

12.9
 結束upstream請求 496

12.10
 小結 499

13章 郵件代理模組 500

13.1
 郵件代理伺服器的功能 500

13.2
 郵件模組的處理框架 503

13.2.1
 一個請求的8個獨立處理階段 503

13.2.2
 郵件類模組的定義 504

13.2.3
 郵件框架的初始化 506

13.3
 初始化請求 506

13.3.1
 描述郵件請求的ngx_mail_session_t結構體 506

13.3.2
 初始化郵件請求的流程 509

13.4
 接收並解析客戶端請求 509

13.5
 郵件認證 510

13.5.1
 ngx_mail_auth_http_ctx_t結構體 510

13.5.2
 與認證伺服器建立連線 511

13.5.3
 傳送請求到認證伺服器 513

13.5.4
 接收並解析響應 514

13.6
 與上游郵件伺服器間的認證互動 514

13.6.1
 ngx_mail_proxy_ctx_t結構體 516

13.6.2
 向上遊郵件伺服器發起連線 516

13.6.3
 與郵件伺服器認證互動的過程 518

13.7
 透傳上游郵件伺服器與客戶端間的流 520

13.8
 小結 524

14章 程式間的通訊機制 525

14.1
 概述 525

14.2
 共享記憶體 526

14.3
 原子操作 530

14.3.1
 不支援原子庫下的原子操作 530

14.3.2
 x86架構下的原子操作 531

14.3.3
 自旋鎖 533

14.4
 Nginx頻道 535

14.5
 訊號 538

14.6
 訊號量 540

14.7
 檔案鎖 541

14.8
 互斥鎖 544

14.8.1
 檔案鎖實現的ngx_shmtx_t 546

14.8.2
 原子變數實現的ngx_shmtx_t 548

14.9
 小結 553

15章 變數 554

15.1
 使用內部變數開發模組 555

15.1.1
 定義模組 556

15.1.2
 定義http模組載入方式 557

15.1.3
 解析配置中的變數 558

15.1.4
 處理請求 560

15.2
 內部變數工作原理 561

15.2.1
 何時定義變數 561

15.2.2
 相關資料結構詳述 564

15.2.3
 定義變數的方法 572

15.2.4
 使用變數的方法 572

15.2.5
 如何解析變數 573

15.3
 定義內部變數 576

15.4
 外部變數與指令碼引擎 577

15.4.1
 相關資料結構 578

15.4.2
 編譯“set”指令碼 581

15.4.3
 指令碼執行流程 586

15.5
 小結 589

16章 slab共享記憶體 590

16.1
 操作slab共享記憶體的方法 590

16.2
 使用slab共享記憶體池的例子 592

16.2.1
 共享記憶體中的資料結構 593

16.2.2
 操作共享記憶體中的紅黑樹與連結串列 595

16.2.3
 解析配置檔案 600

16.2.4
 定義模組 603

16.3
 slab記憶體管理的實現原理 605

16.3.1
 記憶體結構佈局 607

16.3.2
 分配記憶體流程 613

16.3.3
 釋放記憶體流程 617

16.3.4
 如何使用位操作 619

16.3.5
 slab記憶體池間的管理 624

16.4
 小結 624

前 言

Preface?前  言為什麼要寫這本書自第1版發行以來,筆者很欣慰得到了廣大讀者的認可。本書一直致力於說明開發Nginx模組的必備知識,然而由於Nginx功能繁多且效能強大,以致必須要了解的基本技能也很龐雜,而第1版成書匆忙,缺失了幾個進階的技巧描述(例如如何使用變數、slab共享記憶體等),因此決定在第1版的基礎上進一步完善。
事實上,我們總能在nginx.conf配置檔案中看到各種帶著$符號的變數,只要修改帶著變數的這一行行配置,就可以不用編譯、部署而使得Nginx具備新功能,這些支援變數的Nginx模組提供了極為靈活的功能,第2版通過新增的第15章詳細介紹瞭如何在模組中支援HTTP變數,包括如何在程式碼中使用其他Nginx模組提供的變數,以及如何定義新的變數供nginx.conf和其他第三方模組使用等。第16章介紹了slab共享記憶體,這是一套適用於小塊記憶體快速分配釋放的記憶體管理方式,它非常高效,分配與釋放速度都是以納秒計算的,常用於多個worker程式之間的通訊,這比第14章介紹的原始的共享記憶體通訊方式要先進很多。第16章不僅詳細介紹了它的實現方式,也探討了它的優缺點,比如,如果模組間要共享的單個物件常常要消耗數KB的空間,這時就需要修改它的實現(例如增大定義的slab頁大小),以避免記憶體的浪費等。
Nginx記憶體池在第1版中只是簡單帶過,第2版中新增了8.7節介紹了記憶體池的實現細節,以幫助讀者用好最基礎的記憶體池功能。

此外,很多讀者反饋需要結合TCP來談談Nginx,因此在9.10節中筆者試圖在不陷入Linux核心細節的情況下,簡要介紹了TCP以清晰瞭解Nginx的事件框架,瞭解Nginx的高併發能力。
這一版新增的第15章的樣例程式碼可以從http://nginx.taohui.org.cn站點上下載。
因筆者工作繁忙,以致第2版拖稿嚴重,讀者的郵件也無法及時回覆,非常抱歉。從這版開始會把曾經的回覆整理後放在網站上,想必這比回覆郵件要更有效率些。
讀者物件本書適合以下讀者閱讀。
對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章介紹了程式間同步的工具。第15章介紹了HTTP變數,包括如何使用已有變數、支援使用者在nginx.conf中修改變數的值、支援其他模組開發者使用自己定義的變數等。第16章介紹了slab共享記憶體,該記憶體極為高效,可用於多個worker程式間的通訊。
為了不讓讀者陷入程式碼的“汪洋大海”中,在本書中大量使用了圖表,這樣可以使讀者快速、大體地瞭解流程和原理,在這基礎上,如果讀者還希望瞭解程式碼是如何實現的,可以針對性地閱讀原始碼中的相應方法。在程式碼的關鍵地方會通過新增註釋的方式加以說明。希望這種方式能夠幫助讀者減少閱讀花費的時間,更快、更好地把握住Nginx,同時深入到細節中。
寫作本書第1版時,Nginx的最新穩定版本是1.0.14,所以當時是基於此版本來寫作的。截止到第2版完成時,Nginx的穩定版本已經上升到了1.8.0。但這不會對本書的閱讀造成困惑,筆者驗證過示例程式碼,均可以執行在最新版本的Nginx中,這是因為本書主要是在介紹Nginx的基本框架程式碼,以及怎樣使用這些框架程式碼開發新的Nginx模組。在這些基本框架程式碼中,Nginx一般不會做任何改變,否則已有的大量Nginx模組將無法工作,這種損失是不可承受的。而且Nginx框架為具體的功能模組提供了足夠的靈活性,修改功能時很少需要修改框架程式碼。
Nginx是跨平臺的伺服器,然而這本書將只針對於最常見的Linux作業系統進行分析,這樣做一方面是篇幅所限,另一方面則是本書的寫作目的主要在於告訴大家如何基於Nginx編寫程式碼,而不是怎樣在一個具體的作業系統上修改配置使用Nginx。因此,即使本書以Linux系統為代表講述Nginx,也不會影響使用其他作業系統的讀者閱讀,作業系統的差別相對於本書內容的影響實在是非常小。
勘誤和支援由於作者的水平有限,加之編寫的時間也很倉促,書中難免會出現一些錯誤或者不準確的地方,懇請讀者批評指正。為此,我特意建立了一個線上支援與應急方案的二級站點:http://nginx.weebly.com。讀者可以將書中的錯誤釋出在Bug勘誤表頁面中,同時如果讀者遇到任何問題,也可以訪問Q&A頁面,我將盡量線上上為讀者提供最滿意的解答。書中的全部原始檔都將釋出在這個網站上,我也會將相應的功能更新及時釋出出來。如果你有更多的寶貴意見,也歡迎你傳送郵件至我的郵箱russelltao@foxmail.com,期待能夠聽到讀者的真摯反饋。
致謝我首先要感謝Igor Sysoev,他在Nginx設計上展現的功力令人折服,正是他的工作成果才有了本書誕生的意義。
lisa是機械工業出版社華章公司的優秀編輯,非常值得信任。在這半年的寫作過程中,她花費了很多時間、精力來閱讀我的書稿,指出了許多文字上和格式上的錯誤,她提出的建議都大大提高了本書的可讀性。
在這半年時間裡,一邊工作一邊寫作給我帶來了很大的壓力,所以我要感謝我的父母在生活上對我無微不至的照顧,使我可以全力投入到寫作中。繁忙的工作之餘,寫作又佔用了休息時間的絕大部分,感謝我的太太毛業勤對我的體諒和鼓勵,讓我始終以高昂的鬥志投入到本書的寫作中。
感謝我工作中的同事們,正是在與他們一起戰鬥在一線的日子裡,我才不斷地對技術有新地感悟;正是那些充滿激情的歲月,才使得我越來越熱愛伺服器技術的開發。
謹以此書,獻給我最親愛的家人,以及眾多熱愛Nginx的朋友。
陶輝2015年10月

相關文章