深入理解Nginx:模塊開發(fā)與架構(gòu)解析

2021-04-16 19:25 更新
深入理解Nginx:模塊開發(fā)與架構(gòu)解析


陶輝 著

  • 出版社: 機(jī)械工業(yè)出版社
  • ISBN:9787111414780
  • 版次:1
  • 商品編碼:11217076
  • 品牌:機(jī)工出版
  • 包裝:平裝
  • 叢書名: 揭秘系列叢書
  • 外文名稱:Understanding Nginx
  • 開本:16開
  • 出版時(shí)間:2013-04-05
  • 用紙:膠版紙
  • 頁數(shù):584
  • 正文語種:中文


點(diǎn)此購買


編輯推薦

《深入理解Nginx:模塊開發(fā)與架構(gòu)解析》由阿里巴巴資深Nginx專家撰寫,透徹解析Nginx架構(gòu),詳解Nginx模塊開發(fā)方法和技巧。

內(nèi)容簡介

  《深入理解Nginx:模塊開發(fā)與架構(gòu)解析》是阿里巴巴資深Nginx技術(shù)專家嘔心瀝血之作,是作者多年的經(jīng)驗(yàn)結(jié)晶,也是目前市場上一本通過還原Nginx設(shè)計(jì)思想,剖析Nginx架構(gòu)來幫助讀者快速高效開發(fā)HTTP模塊的圖書。
  《深入理解Nginx:模塊開發(fā)與架構(gòu)解析》首先通過介紹官方Nginx的基本用法和配置規(guī)則,幫助讀者了解一般Nginx模塊的用法,然后重點(diǎn)介紹如何開發(fā)HTTP模塊(含HTTP過濾模塊)來得到定制的Nginx,其中包括開發(fā)一個(gè)功能復(fù)雜的模塊所需要了解的各種知識,如Nginx的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)、配置項(xiàng)的解析、記錄日志的工具以及upstream、subrequest的使用方法等。在此基礎(chǔ)上,綜合Nginx框架代碼分析Nginx的架構(gòu),介紹其設(shè)計(jì)理念和技巧,進(jìn)一步幫助讀者自由、有效地開發(fā)出功能豐富、性能一流的Nginx模塊。

作者簡介

  陶輝,思科后臺工程師,從事服務(wù)端開發(fā)近十年,擅長Linux分布式架構(gòu)下的海量數(shù)據(jù)處理,擅長C/C++開發(fā)的高性能高吞吐量網(wǎng)絡(luò)服務(wù),曾任思科DMS后臺架構(gòu)設(shè)計(jì)工作,曾在騰訊QQ空間后臺個(gè)人信息中心、個(gè)人檔、漂流瓶、空間日志、花藤、好友買賣等項(xiàng)目中擔(dān)任服務(wù)器設(shè)計(jì)與開發(fā)工作,曾在華為中央軟件部綜合網(wǎng)管平臺擔(dān)任北向接口設(shè)計(jì)開發(fā)工作。擁有豐富的Linux高性能服務(wù)器開發(fā)經(jīng)驗(yàn),豐富的云存儲系統(tǒng)開發(fā)經(jīng)驗(yàn),目前關(guān)注云文檔管理系統(tǒng)和Nginx的再開發(fā)。


目錄

前 言
第一部分 Nginx能幫我們做什么
第1章 研究Nginx前的準(zhǔn)備工作
1.1 Nginx是什么
1.2 為什么選擇Nginx
1.3 準(zhǔn)備工作
1.3.1 Linux操作系統(tǒng)
1.3.2 使用Nginx的必備軟件
1.3.3 磁盤目錄
1.3.4 Linux內(nèi)核參數(shù)的優(yōu)化
1.3.5 獲取Nginx源碼
1.4 編譯安裝Nginx
1.5 configure詳解
1.5.1 configure的命令參數(shù)
1.5.2 configure執(zhí)行流程
1.5.3 configure生成的文件
1.6 Nginx的命令行控制
1.7 小結(jié)
第2章 Nginx的配置
2.1 運(yùn)行中的Nginx進(jìn)程間的關(guān)系
2.2 Nginx配置的通用語法
2.2.1 塊配置項(xiàng)
2.2.2 配置項(xiàng)的語法格式
2.2.3 配置項(xiàng)的注釋
2.2.4 配置項(xiàng)的單位
2.2.5 在配置中使用變量
2.3 Nginx服務(wù)的基本配置
2.3.1 用于調(diào)試進(jìn)程和定位問題的配置項(xiàng)
2.3.2 正常運(yùn)行的配置項(xiàng)
2.3.3 優(yōu)化性能的配置項(xiàng)
2.3.4 事件類配置項(xiàng)
2.4 用HTTP核心模塊配置一個(gè)靜態(tài)Web服務(wù)器
2.4.1 虛擬主機(jī)與請求的分發(fā)
2.4.2 文件路徑的定義
2.4.3 內(nèi)存及磁盤資源的分配
2.4.4 網(wǎng)絡(luò)連接的設(shè)置
2.4.5 MIME類型的設(shè)置
2.4.6 對客戶端請求的限制
2.4.7 文件操作的優(yōu)化
2.4.8 對客戶端請求的特殊處理
2.4.9 ngx_http_core_module模塊提供的變量
2.5 用HTTP proxy module配置一個(gè)反向代理服務(wù)器
2.5.1 負(fù)載均衡的基本配置
2.5.2 反向代理的基本配置
2.6 小結(jié)
第二部分 如何編寫HTTP模塊
第3章 開發(fā)一個(gè)簡單的HTTP模塊
3.1 如何調(diào)用HTTP模塊
3.2 準(zhǔn)備工作
3.2.1 整型的封裝
3.2.2 ngx_str_t數(shù)據(jù)結(jié)構(gòu)
3.2.3 ngx_list_t數(shù)據(jù)結(jié)構(gòu)
3.2.4 ngx_table_elt_t數(shù)據(jù)結(jié)構(gòu)
3.2.5 ngx_buf_t數(shù)據(jù)結(jié)構(gòu)
3.2.6 ngx_chain_t數(shù)據(jù)結(jié)構(gòu)
3.3 如何將自己的HTTP模塊編譯進(jìn)Nginx
3.3.1 config文件的寫法
3.3.2 利用configure腳本將定制的模塊加入到Nginx中
3.3.3 直接修改Makefile文件
3.4 HTTP模塊的數(shù)據(jù)結(jié)構(gòu)
3.5 定義自己的HTTP模塊
3.6 處理用戶請求
3.6.1 處理方法的返回值
3.6.2 獲取URI和參數(shù)
3.6.3 獲取HTTP頭部
3.6.4 獲取HTTP包體
3.7 發(fā)送響應(yīng)
3.7.1 發(fā)送HTTP頭部
3.7.2 將內(nèi)存中的字符串作為包體發(fā)送
3.7.3 經(jīng)典的"Hello World"示例
3.8 將磁盤文件作為包體發(fā)送
3.8.1 如何發(fā)送磁盤中的文件
3.8.2 清理文件句柄
3.8.3 支持用戶多線程下載和斷點(diǎn)續(xù)傳
3.9 用C++語言編寫HTTP模塊
3.9.1 編譯方式的修改
3.9.2 程序中的符號轉(zhuǎn)換
3.10 小結(jié)
第4章 配置、error日志和請求上下文
4.1 http配置項(xiàng)的使用場景
4.2 怎樣使用http配置
4.2.1 分配用于保存配置參數(shù)的數(shù)據(jù)結(jié)構(gòu)
4.2.2 設(shè)定配置項(xiàng)的解析方式
4.2.3 使用14種預(yù)設(shè)方法解析配置項(xiàng)
4.2.4 自定義配置項(xiàng)處理方法
4.2.5 合并配置項(xiàng)
4.3 HTTP配置模型
4.3.1 解析HTTP配置的流程
4.3.2 HTTP配置模型的內(nèi)存布局
4.3.3 如何合并配置項(xiàng)
4.3.4 預(yù)設(shè)配置項(xiàng)處理方法的工作原理
4.4 error日志的用法
4.5 請求的上下文
4.5.1 上下文與全異步Web服務(wù)器的關(guān)系
4.5.2 如何使用HTTP上下文
4.5.3 HTTP框架如何維護(hù)上下文結(jié)構(gòu)
4.6 小結(jié)
第5章 訪問第三方服務(wù)
5.1 upstream的使用方式
5.1.1 ngx_http_upstream_t結(jié)構(gòu)體
5.1.2 設(shè)置upstream的限制性參數(shù)
5.1.3 設(shè)置需要訪問的第三方服務(wù)器地址
5.1.4 設(shè)置回調(diào)方法
5.1.5 如何啟動upstream機(jī)制
5.2 回調(diào)方法的執(zhí)行場景
5.2.1 create_request回調(diào)方法
5.2.2 reinit_request回調(diào)方法
5.2.3 finalize_request回調(diào)方法
5.2.4 process_header回調(diào)方法
5.2.5 rewrite_redirect回調(diào)方法
5.2.6 input_filter_init與input_filter回調(diào)方法
5.3 使用upstream的示例
5.3.1 upstream的各種配置參數(shù)
5.3.2 請求上下文
5.3.3 在create_request方法中構(gòu)造請求
5.3.4 在process_header方法中解析包頭
5.3.5 在finalize_request方法中釋放資源
5.3.6 在ngx_http_mytest_handler方法中啟動upstream
5.4 subrequest的使用方式
5.4.1 配置子請求的處理方式
5.4.2 實(shí)現(xiàn)子請求處理完畢時(shí)的回調(diào)方法
5.4.3 處理父請求被重新激活后的回調(diào)方法
5.4.4 啟動subrequest子請求
5.5 subrequest執(zhí)行過程中的主要場景
5.5.1 如何啟動subrequest
5.5.2 如何轉(zhuǎn)發(fā)多個(gè)子請求的響應(yīng)包體
5.5.3 子請求如何激活父請求
5.6 subrequest使用的例子
5.6.1 配置文件中子請求的設(shè)置
5.6.2 請求上下文
5.6.3 子請求結(jié)束時(shí)的處理方法
5.6.4 父請求的回調(diào)方法
5.6.5 啟動subrequest
5.7 小結(jié)
第6章 開發(fā)一個(gè)簡單的HTTP過濾模塊
6.1 過濾模塊的意義
6.2 過濾模塊的調(diào)用順序
6.2.1 過濾鏈表是如何構(gòu)成的
6.2.2 過濾鏈表的順序
6.2.3 官方默認(rèn)HTTP過濾模塊的功能簡介
6.3 HTTP過濾模塊的開發(fā)步驟
6.4 HTTP過濾模塊的簡單例子
6.4.1 如何編寫config文件
6.4.2 配置項(xiàng)和上下文
6.4.3 定義HTTP過濾模塊
6.4.4 初始化HTTP過濾模塊
6.4.5 處理請求中的HTTP頭部
6.4.6 處理請求中的HTTP包體
6.5 小結(jié)
第7章 Nginx提供的高級數(shù)據(jù)結(jié)構(gòu)
7.1 Nginx提供的高級數(shù)據(jù)結(jié)構(gòu)概述
7.2 ngx_queue_t雙向鏈表
7.2.1 為什么設(shè)計(jì)ngx_queue_t雙向鏈表
7.2.2 雙向鏈表的使用方法
7.2.3 使用雙向鏈表排序的例子
7.2.4 雙向鏈表是如何實(shí)現(xiàn)的
7.3 ngx_array_t動態(tài)數(shù)組
7.3.1 為什么設(shè)計(jì)ngx_array_t動態(tài)數(shù)組
7.3.2 動態(tài)數(shù)組的使用方法
7.3.3 使用動態(tài)數(shù)組的例子
7.3.4 動態(tài)數(shù)組的擴(kuò)容方式
7.4 ngx_list_t單向鏈表
7.5 ngx_rbtree_t紅黑樹
7.5.1 為什么設(shè)計(jì)ngx_rbtree_t紅黑樹
7.5.2 紅黑樹的特性
7.5.3 紅黑樹的使用方法
7.5.4 使用紅黑樹的簡單例子
7.5.5 如何自定義添加成員方法
7.6 ngx_radix_tree_t基數(shù)樹
7.6.1 ngx_radix_tree_t基數(shù)樹的原理
7.6.2 基數(shù)樹的使用方法
7.6.3 使用基數(shù)樹的例子
7.7 支持通配符的散列表
7.7.1 ngx_hash_t基本散列表
7.7.2 支持通配符的散列表
7.7.3 帶通配符散列表的使用例子
7.8 小結(jié)
第三部分 深入Nginx
第8章 Nginx基礎(chǔ)架構(gòu)
8.1 Web服務(wù)器設(shè)計(jì)中的關(guān)鍵約束
8.2 Nginx的架構(gòu)設(shè)計(jì)
8.2.1 優(yōu)秀的模塊化設(shè)計(jì)
8.2.2 事件驅(qū)動架構(gòu)
8.2.3 請求的多階段異步處理
8.2.4 管理進(jìn)程、多工作進(jìn)程設(shè)計(jì)
8.2.5 平臺無關(guān)的代碼實(shí)現(xiàn)
8.2.6 內(nèi)存池的設(shè)計(jì)
8.2.7 使用統(tǒng)一管道過濾器模式的HTTP過濾模塊
8.2.8 其他一些用戶模塊
8.3 Nginx框架中的核心結(jié)構(gòu)體ngx_cycle_t
8.3.1 ngx_listening_t結(jié)構(gòu)體
8.3.2 ngx_cycle_t結(jié)構(gòu)體
8.3.3 ngx_cycle_t支持的方法
8.4 Nginx啟動時(shí)框架的處理流程
8.5 worker進(jìn)程是如何工作的
8.6 master進(jìn)程是如何工作的
8.7 小結(jié)
第9章 事件模塊
9.1 事件處理框架概述
9.2 Nginx事件的定義
9.3 Nginx連接的定義
9.3.1 被動連接
9.3.2 主動連接
9.3.3 ngx_connection_t連接池
9.4 ngx_events_module核心模塊
9.4.1 如何管理所有事件模塊的配置項(xiàng)
9.4.2 管理事件模塊
9.5 ngx_event_core_module事件模塊
9.6 epoll事件驅(qū)動模塊
9.6.1 epoll的原理和用法
9.6.2 如何使用epoll
9.6.3 ngx_epoll_module模塊的實(shí)現(xiàn)
9.7 定時(shí)器事件
9.7.1 緩存時(shí)間的管理
9.7.2 緩存時(shí)間的精度
9.7.3 定時(shí)器的實(shí)現(xiàn)
9.8 事件驅(qū)動框架的處理流程
9.8.1 如何建立新連接
9.8.2 如何解決"驚群"問題
9.8.3 如何實(shí)現(xiàn)負(fù)載均衡
9.8.4 post事件隊(duì)列
9.8.5 ngx_process_events_and_timers流程
9.9 文件的異步I/O
9.9.1 Linux內(nèi)核提供的文件異步I/O
9.9.2 ngx_epoll_module模塊中實(shí)現(xiàn)的針對文件的異步I/O
9.10 小結(jié)
第10章 HTTP框架的初始化
10.1 HTTP框架概述
10.2 管理HTTP模塊的配置項(xiàng)
10.2.1 管理main級別下的配置項(xiàng)
10.2.2 管理server級別下的配置項(xiàng)
10.2.3 管理location級別下的配置項(xiàng)
10.2.4 不同級別配置項(xiàng)的合并
10.3 監(jiān)聽端口的管理
10.4 server的快速檢索
10.5 location的快速檢索
10.6 HTTP請求的11個(gè)處理階段
10.6.1 HTTP處理階段的普適規(guī)則
10.6.2 NGX_HTTP_POST_READ_PHASE階段
10.6.3 NGX_HTTP_SERVER_REWRITE_PHASE階段
10.6.4 NGX_HTTP_FIND_CONFIG_PHASE階段
10.6.5 NGX_HTTP_REWRITE_PHASE階段
10.6.6 NGX_HTTP_POST_REWRITE_PHASE階段
10.6.7 NGX_HTTP_PREACCESS_PHASE階段
10.6.8 NGX_HTTP_ACCESS_PHASE階段
10.6.9 NGX_HTTP_POST_ACCESS_PHASE階段
10.6.10 NGX_HTTP_TRY_FILES_PHASE階段
10.6.11 NGX_HTTP_CONTENT_PHASE階段
10.6.12 NGX_HTTP_LOG_PHASE階段
10.7 HTTP框架的初始化流程
10.8 小結(jié)
第11章 HTTP框架的執(zhí)行流程
11.1 HTTP框架執(zhí)行流程概述
11.2 新連接建立時(shí)的行為
11.3 第一次可讀事件的處理
11.4 接收HTTP請求行
11.5 接收HTTP頭部
11.6 處理HTTP請求
11.6.1 ngx_http_core_generic_phase
11.6.2 ngx_http_core_rewrite_phase
11.6.3 ngx_http_core_access_phase
11.6.4 ngx_http_core_content_phase
11.7 subrequest與post請求
11.8 處理HTTP包體
11.8.1 接收包體
11.8.2 放棄接收包體
11.9 發(fā)送HTTP響應(yīng)
11.9.1 ngx_http_send_header
11.9.2 ngx_http_output_filter
11.9.3 ngx_http_writer
11.10 結(jié)束HTTP請求
11.10.1 ngx_http_close_connection
11.10.2 ngx_http_free_request
11.10.3 ngx_http_close_request
11.10.4 ngx_http_finalize_connection
11.10.5 ngx_http_terminate_request
11.10.6 ngx_http_finalize_request
11.11 小結(jié)
第12章 upstream機(jī)制的設(shè)計(jì)與實(shí)現(xiàn)
12.1 upstream機(jī)制概述
12.1.1 設(shè)計(jì)目的
12.1.2 ngx_http_upstream_t數(shù)據(jù)結(jié)構(gòu)的意義
12.1.3 ngx_http_upstream_conf_t配置結(jié)構(gòu)體
12.2 啟動upstream
12.3 與上游服務(wù)器建立連接
12.4 發(fā)送請求到上游服務(wù)器
12.5 接收上游服務(wù)器的響應(yīng)頭部
12.5.1 應(yīng)用層協(xié)議的兩段劃分方式
12.5.2 處理包體的3種方式
12.5.3 接收響應(yīng)頭部的流程
12.6 不轉(zhuǎn)發(fā)響應(yīng)時(shí)的處理流程
12.6.1 input_filter方法的設(shè)計(jì)
12.6.2 默認(rèn)的input_filter方法
12.6.3 接收包體的流程
12.7 以下游網(wǎng)速優(yōu)先來轉(zhuǎn)發(fā)響應(yīng)
12.7.1 轉(zhuǎn)發(fā)響應(yīng)的包頭
12.7.2 轉(zhuǎn)發(fā)響應(yīng)的包體
12.8 以上游網(wǎng)速優(yōu)先來轉(zhuǎn)發(fā)響應(yīng)
12.8.1 ngx_event_pipe_t結(jié)構(gòu)體的意義
12.8.2 轉(zhuǎn)發(fā)響應(yīng)的包頭
12.8.3 轉(zhuǎn)發(fā)響應(yīng)的包體
12.8.4 ngx_event_pipe_read_upstream方法
12.8.5 ngx_event_pipe_write_to_downstream方法
12.9 結(jié)束upstream請求
12.10 小結(jié)
第13章 郵件代理模塊
13.1 郵件代理服務(wù)器的功能
13.2 郵件模塊的處理框架
13.2.1 一個(gè)請求的8個(gè)獨(dú)立處理階段
13.2.2 郵件類模塊的定義
13.2.3 郵件框架的初始化
13.3 初始化請求
13.3.1 描述郵件請求的ngx_mail_session_t結(jié)構(gòu)體
13.3.2 初始化郵件請求的流程
13.4 接收并解析客戶端請求
13.5 郵件認(rèn)證
13.5.1 ngx_mail_auth_http_ctx_t結(jié)構(gòu)體
13.5.2 與認(rèn)證服務(wù)器建立連接
13.5.3 發(fā)送請求到認(rèn)證服務(wù)器
13.5.4 接收并解析響應(yīng)
13.6 與上游郵件服務(wù)器間的認(rèn)證交互
13.6.1 ngx_mail_proxy_ctx_t結(jié)構(gòu)體
13.6.2 向上游郵件服務(wù)器發(fā)起連接
13.6.3 與郵件服務(wù)器認(rèn)證交互的過程
13.7 透傳上游郵件服務(wù)器與客戶端間的流
13.8 小結(jié)
第14章 進(jìn)程間的通信機(jī)制
14.1 概述
14.2 共享內(nèi)存
14.3 原子操作
14.3.1 不支持原子庫下的原子操作
14.3.2 x86架構(gòu)下的原子操作
14.3.3 自旋鎖
14.4 Nginx頻道
14.5 信號
14.6 信號量
14.7 文件鎖
14.8 互斥鎖
14.8.1 文件鎖實(shí)現(xiàn)的ngx_shmtx_t鎖
14.8.2 原子變量實(shí)現(xiàn)的ngx_shmtx_t鎖
14.9 小結(jié)


精彩書摘


  3)如果handler方法返回NGX_DONE,則意味著剛才的handler方法無法在這一次調(diào)度中處理完這一個(gè)階段,它需要多次的調(diào)度才能完成。注意,此時(shí)返回NGX—OK,它會使得HTTP框架立刻把控制權(quán)交還給epoll等事件模塊,不再處理當(dāng)前請求,唯有這個(gè)請求上的事件再次被觸發(fā)時(shí)才會繼續(xù)執(zhí)行。
  4)如果handler方法返回除去NGX_DECLINED或者NGX_DONE以外的其他值,則調(diào)用ngx_http_finalize_request結(jié)束請求,其參數(shù)為handler方法的返回值。
  可以注意到,ngx_http_core_rewrite_phase方法與ngx_http_core_generic_phase方法有一個(gè)顯著的不同點(diǎn):前者永遠(yuǎn)不會導(dǎo)致跨過同一個(gè)HTTP階段的其他處理方法,就直接跳到下一個(gè)階段來處理請求。原因其實(shí)很簡單,可能有許多HTTP模塊在NGX HTTP SERVERREWRITE_PHASE和NGX_HTTP_REWRITE_PHASE階段同時(shí)處理重寫URL這樣的業(yè)務(wù),HTTP框架認(rèn)為這兩個(gè)階段的HTTP模塊是完全平等的,序號靠前的HTTP模塊優(yōu)先級并不會更高,它不能決定序號靠后的HTTP模塊是否可以再次重寫URL。因此,ngx http corerewrite_phase方法絕對不會把phase_handler直接設(shè)置到下一個(gè)階段處理方法的流程中,即不可能存在類似下面的代碼。
  11.6.3 ngx http core access phase
  ngx_http_core_access—phase方法是僅用于NGX_HTTP_ACCESS_PHASE階段的處理方法,這一階段用于控制用戶發(fā)起的請求是否合法,如檢測客戶端的IP地址是否允許訪問。它涉及nginx.conf配置文件中satisfy配置項(xiàng)的參數(shù)值,見表11—2。
  對于表11—2的any配置項(xiàng),是通過ngx_http_request_t結(jié)構(gòu)體中的access_code成員來傳遞handler方法的返回值的,因此,ngx_http_core_access_phase方法會比較復(fù)雜,如圖11—10所示。
 

前言/序言

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


點(diǎn)此購買 


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號