Nginx完全開發(fā)指南(使用C、C++和OpenResty)_第1頁
Nginx完全開發(fā)指南(使用C、C++和OpenResty)_第2頁
Nginx完全開發(fā)指南(使用C、C++和OpenResty)_第3頁
Nginx完全開發(fā)指南(使用C、C++和OpenResty)_第4頁
Nginx完全開發(fā)指南(使用C、C++和OpenResty)_第5頁
已閱讀5頁,還剩203頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

Nginx完全開發(fā)指南使用C、C++和OpenResty注:因內(nèi)容過長上傳受限制,本文檔只顯示部分內(nèi)容,完整版文檔請下載此文檔后留言謝謝。目錄TOC\h\h第0章導(dǎo)讀\h0.1關(guān)于本文\h0.2讀者對象\h0.3讀者要求\h0.4運行環(huán)境\h0.5本文的結(jié)構(gòu)\h0.6如何閱讀本文\h0.7本文的源碼\h第1章Nginx入門\h1.1關(guān)于Nginx\h1.1.1歷史\h1.1.2特點\h1.1.3進(jìn)程模型\h1.1.4版本\h1.2安裝Nginx\h1.2.1準(zhǔn)備工作\h1.2.2快速安裝\h1.2.3運行命令\h1.2.4驗證安裝\h1.2.5定制安裝\h1.3配置Nginx\h1.3.1配置文件格式\h1.3.2進(jìn)程配置\h1.3.3動態(tài)模塊配置\h1.3.4運行日志配置\h1.3.5events配置\h1.3.6http配置\h1.3.7server配置\h1.3.8location配置\h1.3.9file配置\h1.3.10upstream配置\h1.3.11變量\h1.4總結(jié)\h第2章Nginx開發(fā)準(zhǔn)備\h2.1開發(fā)環(huán)境\h2.1.1C++標(biāo)準(zhǔn)\h2.1.2Boost程序庫\h2.2目錄結(jié)構(gòu)\h2.3源碼特點\h2.3.1代碼風(fēng)格\h2.3.2代碼優(yōu)化\h2.3.3面向?qū)ο笏枷隲h2.4使用C++\h2.4.1實現(xiàn)原則\h2.4.2代碼風(fēng)格\h2.4.3編譯腳本\h2.5C++包裝類\h2.5.1類定義\h2.5.2構(gòu)造和析構(gòu)\h2.5.3成員函數(shù)\h2.6總結(jié)\h第3章Nginx基礎(chǔ)設(shè)施\h3.1頭文件\h3.1.1Nginx頭文件\h3.1.2C++頭文件\h3.2整數(shù)類型\h3.2.1標(biāo)準(zhǔn)整數(shù)類型\h3.2.2自定義整數(shù)類型\h3.2.3無效值\h3.2.4C++封裝\h3.3錯誤處理\h3.3.1錯誤碼定義\h3.3.2C++異常\h3.4內(nèi)存池\h3.4.1結(jié)構(gòu)定義\h3.4.2操作函數(shù)\h3.4.3C++封裝\h3.4.4清理機(jī)制\h3.4.5C++內(nèi)存分配器\h3.5字符串\h3.5.1結(jié)構(gòu)定義\h3.5.2操作函數(shù)\h3.5.3C++封裝\h3.6時間與日期\h3.6.1時間結(jié)構(gòu)定義\h3.6.2時間操作函數(shù)\h3.6.3日期結(jié)構(gòu)定義\h3.6.4日期操作函數(shù)\h3.6.5C++封裝時間\h3.6.6C++封裝日期\h3.7運行日志\h3.7.1結(jié)構(gòu)定義\h3.7.2操作函數(shù)\h3.7.3C++封裝\h3.8總結(jié)\h第4章Nginx高級數(shù)據(jù)結(jié)構(gòu)\h4.1動態(tài)數(shù)組\h4.1.1結(jié)構(gòu)定義\h4.1.2操作函數(shù)\h4.1.3C++動態(tài)數(shù)組\h4.2單向鏈表\h4.2.1結(jié)構(gòu)定義\h4.2.2操作函數(shù)\h4.2.3C++迭代器\h4.2.4C++單向鏈表\h4.3雙端隊列\(zhòng)h4.3.1結(jié)構(gòu)定義\h4.3.2操作函數(shù)\h4.3.3C++節(jié)點\h4.3.4C++迭代器\h4.3.5C++雙端隊列\(zhòng)h4.4紅黑樹\h4.4.1節(jié)點結(jié)構(gòu)定義\h4.4.2樹結(jié)構(gòu)定義\h4.4.3操作函數(shù)\h4.4.4C++紅黑樹\h4.5緩沖區(qū)\h4.5.1結(jié)構(gòu)定義\h4.5.2操作函數(shù)\h4.5.3C++緩沖區(qū)\h4.6數(shù)據(jù)塊鏈\h4.6.1結(jié)構(gòu)定義\h4.6.2操作函數(shù)\h4.6.3C++節(jié)點\h4.6.4C++迭代器\h4.6.5C++數(shù)據(jù)塊鏈\h4.7鍵值對\h4.7.1簡單鍵值對\h4.7.2散列表鍵值對\h4.8總結(jié)\h第5章Nginx開發(fā)綜述\h5.1最簡單的模塊\h5.1.1模塊設(shè)計\h5.1.2配置解析\h5.1.3處理函數(shù)\h5.1.4模塊集成\h5.1.5編譯腳本和命令\h5.1.6測試驗證\h5.2開發(fā)基本流程\h5.2.1設(shè)計\h5.2.2開發(fā)\h5.2.3編譯\h5.2.4測試驗證\h5.2.5調(diào)優(yōu)\h5.2.6流程圖\h5.3編譯腳本\h5.3.1運行機(jī)制\h5.3.2使用的變量\h5.3.3模塊腳本\h5.3.4兩種腳本格式\h5.3.5舊式編譯腳本\h5.4總結(jié)\h第6章Nginx模塊體系\h6.1模塊架構(gòu)\h6.1.1結(jié)構(gòu)定義\h6.1.2模塊的簽名\h6.1.3模塊的種類\h6.1.4模塊的函數(shù)指針表\h6.1.5模塊的類圖\h6.1.6模塊的組織形式\h6.1.7模塊的初始化\h6.1.8模塊的動態(tài)加載\h6.2配置解析\h6.2.1結(jié)構(gòu)定義\h6.2.2配置解析的基本流程\h6.2.3配置數(shù)據(jù)的存儲模型\h6.2.4訪問配置數(shù)據(jù)\h6.2.5確定配置數(shù)據(jù)的位置\h6.2.6配置解析函數(shù)\h6.2.7配置數(shù)據(jù)的合并\h6.2.8配置指令的類型\h6.3源碼分析\h6.3.1ngx_core_module\h6.3.2ngx_errlog_module\h6.4C++封裝\h6.4.1NgxModuleConfig\h6.4.2NgxModule\h6.4.3NgxTake\h6.4.4NGX_MODULE_NULL\h6.5C++開發(fā)模塊\h6.5.1模塊的基本組成\h6.5.2配置信息類\h6.5.3業(yè)務(wù)邏輯類\h6.5.4模塊集成類\h6.5.5實現(xiàn)源文件\h6.5.6增加更多功能\h6.6總結(jié)\h第7章NginxHTTP框架綜述\h7.1框架簡介\h7.1.1模塊分類\h7.1.2處理流程\h7.1.3請求結(jié)構(gòu)體\h7.1.4請求的處理階段\h7.1.5請求的環(huán)境數(shù)據(jù)\h7.2處理引擎\h7.2.1函數(shù)原型\h7.2.2處理函數(shù)的存儲方式\h7.2.3內(nèi)容處理函數(shù)\h7.2.4引擎的數(shù)據(jù)結(jié)構(gòu)\h7.2.5引擎的初始化\h7.2.6引擎的運行機(jī)制\h7.2.7日志階段的處理\h7.3過濾引擎\h7.3.1函數(shù)原型\h7.3.2過濾函數(shù)鏈表\h7.3.3過濾函數(shù)的順序\h7.3.4過濾鏈表的運行機(jī)制\h7.3.5請求體過濾\h7.4源碼分析\h7.4.1ngx_http_static_module\h7.4.2ngx_http_not_modified_filter_module\h7.5C++封裝\h7.5.1NgxModuleCtx\h7.5.2NgxHttpCoreModule\h7.5.3NgxFilter\h7.6總結(jié)\h第8章NginxHTTP請求處理\h8.1狀態(tài)碼\h8.2請求結(jié)構(gòu)體\h8.3請求行\(zhòng)h8.3.1請求方法\h8.3.2協(xié)議版本號\h8.3.3資源標(biāo)識符\h8.4請求頭\h8.5請求體\h8.5.1結(jié)構(gòu)定義\h8.5.2操作函數(shù)\h8.6響應(yīng)頭\h8.6.1結(jié)構(gòu)定義\h8.6.2操作函數(shù)\h8.7響應(yīng)體\h8.8源碼分析\h8.8.1ngx_http_static_module\h8.8.2ngx_http_not_modified_filter_module\h8.9C++封裝\h8.9.1NgxHeaders\h8.9.2NgxRequestBody\h8.9.3NgxRequest\h8.9.4NgxResponse\h8.10開發(fā)handler模塊\h8.10.1模塊設(shè)計\h8.10.2配置信息類\h8.10.3業(yè)務(wù)邏輯類\h8.10.4模塊集成類\h8.10.5實現(xiàn)源文件\h8.10.6編譯腳本\h8.10.7測試驗證\h8.11開發(fā)filter模塊\h8.11.1模塊設(shè)計\h8.11.2配置信息類\h8.11.3環(huán)境數(shù)據(jù)類\h8.11.4業(yè)務(wù)邏輯類\h8.11.5模塊集成類\h8.11.6實現(xiàn)源文件\h8.11.7編譯腳本\h8.11.8測試驗證\h8.12總結(jié)\h第9章NginxHTTP請求轉(zhuǎn)發(fā)\h9.1框架簡介\h9.1.1工作原理\h9.1.2請求結(jié)構(gòu)體\h9.1.3上游結(jié)構(gòu)體\h9.1.4上游配置參數(shù)\h9.2請求轉(zhuǎn)發(fā)機(jī)制\h9.2.1回調(diào)函數(shù)\h9.2.2初始化\h9.2.3設(shè)置連接參數(shù)\h9.2.4啟動連接\h9.2.5處理數(shù)據(jù)\h9.3負(fù)載均衡機(jī)制\h9.3.1結(jié)構(gòu)定義\h9.3.2初始化模塊入口\h9.3.3初始化地址列表\h9.3.4初始化算法\h9.3.5執(zhí)行算法\h9.4源碼分析\h9.4.1ngx_http_memcached_module\h9.4.2ngx_http_upstream_ip_hash_module\h9.5C++封裝\h9.5.1NgxUpstream\h9.5.2NgxUpstreamHelper\h9.5.3NgxHttpUpstreamModule\h9.5.4NgxLoadBalance\h9.6開發(fā)upstream模塊\h9.6.1模塊設(shè)計\h9.6.2配置信息類\h9.6.3業(yè)務(wù)邏輯類\h9.6.4模塊集成類\h9.6.5實現(xiàn)源文件\h9.6.6編譯腳本\h9.6.7測試驗證\h9.7開發(fā)load-balance模塊\h9.7.1模塊設(shè)計\h9.7.2配置信息類\h9.7.3業(yè)務(wù)邏輯類\h9.7.4模塊集成類\h9.7.5實現(xiàn)源文件\h9.7.6編譯腳本\h9.7.7測試驗證\h9.8總結(jié)\h第10章NginxHTTP子請求\h10.1子請求簡介\h10.1.1工作原理\h10.1.2請求結(jié)構(gòu)體\h10.1.3回調(diào)函數(shù)\h10.1.4待處理請求鏈表\h10.1.5子請求存儲結(jié)構(gòu)\h10.2子請求運行機(jī)制\h10.2.1創(chuàng)建子請求\h10.2.2處理引擎\h10.2.3數(shù)據(jù)整理\h10.3C++封裝\h10.3.1NgxSubRequestHandler\h10.3.2NgxSubRequest\h10.4數(shù)據(jù)回傳模塊\h10.4.1模塊設(shè)計\h10.4.2環(huán)境數(shù)據(jù)類\h10.4.3業(yè)務(wù)邏輯類\h10.4.4模塊集成類\h10.4.5編譯腳本\h10.5在模塊里使用子請求\h10.5.1模塊設(shè)計\h10.5.2配置信息類\h10.5.3業(yè)務(wù)邏輯類\h10.5.4測試驗證\h10.6總結(jié)\h第11章Nginx變量\h11.1結(jié)構(gòu)定義\h11.1.1變量值\h11.1.2變量訪問對象\h11.1.3變量的存儲\h11.1.4請求結(jié)構(gòu)體\h11.2運行機(jī)制\h11.2.1注冊變量\h11.2.2獲取變量\h11.2.3修改變量\h11.3復(fù)雜變量\h11.3.1結(jié)構(gòu)定義\h11.3.2運行機(jī)制\h11.4C++封裝\h11.4.1NgxVariableValue\h11.4.2NgxVariable\h11.4.3NgxVarManager\h11.4.4NgxVariables\h11.4.5NgxComplexValue\h11.5在模塊里使用變量\h11.5.1添加變量\h11.5.2讀寫變量\h11.6在模塊里使用復(fù)雜變量\h11.6.1配置信息類\h11.6.2業(yè)務(wù)邏輯類\h11.6.3模塊集成類\h11.6.4測試驗證\h11.7總結(jié)\h第12章Nginx輔助設(shè)施\h12.1摘要算法\h12.1.1MD5\h12.1.2SHA-1\h12.1.3MurmurHash\h12.1.4C++封裝\h12.2編碼和解碼\h12.2.1CRC校驗\h12.2.2Base64編碼解碼\h12.2.3URI編碼解碼\h12.2.4HTML和JSON編碼\h12.3正則表達(dá)式\h12.4共享內(nèi)存\h12.4.1結(jié)構(gòu)定義\h12.4.2操作函數(shù)\h12.4.3C++共享內(nèi)存\h12.5總結(jié)\h第13章Nginx進(jìn)程機(jī)制\h13.1基本系統(tǒng)調(diào)用\h13.1.1errno\h13.1.2getrlimit\h13.2進(jìn)程系統(tǒng)調(diào)用\h13.2.1getpid\h13.2.2fork\h13.2.3waitpid\h13.3信號系統(tǒng)調(diào)用\h13.3.1kill\h13.3.2sigaction\h13.3.3sigsuspend\h13.4結(jié)構(gòu)定義\h13.4.1ngx_cycle_t\h13.4.2ngx_core_conf_t\h13.4.3ngx_process_t\h13.5全局變量\h13.5.1命令行相關(guān)\h13.5.2操作系統(tǒng)相關(guān)\h13.5.3進(jìn)程功能相關(guān)\h13.5.4信號功能相關(guān)\h13.6啟動過程\h13.6.1基本流程\h13.6.2解析命令行\(zhòng)h13.6.3版本和幫助信息\h13.6.4初始化cycle\h13.6.5測試配置\h13.6.6發(fā)送信號\h13.6.7守護(hù)進(jìn)程化\h13.6.8啟動工作進(jìn)程\h13.6.9流程圖\h13.7信號處理\h13.7.1信號處理函數(shù)\h13.7.2發(fā)送信號\h13.7.3處理信號\h13.8單進(jìn)程模式\h13.8.1single進(jìn)程\h13.8.2single進(jìn)程流程圖\h13.9多進(jìn)程模式\h13.9.1產(chǎn)生子進(jìn)程\h13.9.2master進(jìn)程\h13.9.3master進(jìn)程流程圖\h13.9.4worker進(jìn)程\h13.9.5worker進(jìn)程流程圖\h13.10總結(jié)\h第14章Nginx事件機(jī)制\h14.1基本系統(tǒng)調(diào)用\h14.1.1errno\h14.1.2ioctl\h14.1.3setitimer\h14.1.4gettimeofday\h14.2socket系統(tǒng)調(diào)用\h14.2.1socket\h14.2.2bind\h14.2.3listen\h14.2.4accept\h14.2.5connect\h14.2.6recv\h14.2.7send\h14.2.8setsockopt\h14.2.9close\h14.2.10函數(shù)關(guān)系圖\h14.3epoll系統(tǒng)調(diào)用\h14.3.1epoll_create\h14.3.2epoll_ctl\h14.3.3epoll_wait\h14.3.4LT和ET\h14.3.5函數(shù)關(guān)系圖\h14.4結(jié)構(gòu)定義\h14.4.1ngx_event_t\h14.4.2ngx_connection_t\h14.4.3ngx_listening_t\h14.4.4ngx_cycle_t\h14.4.5ngx_os_io_t\h14.4.6ngx_event_actions_t\h14.4.7ngx_posted_events\h14.4.8結(jié)構(gòu)關(guān)系圖\h14.5定時器\h14.5.1紅黑樹\h14.5.2操作函數(shù)\h14.5.3超時處理\h14.6模塊體系\h14.6.1函數(shù)指針表\h14.6.2模塊的組織形式\h14.6.3核心配置\h14.6.4epoll模塊\h14.7全局變量\h14.7.1更新時間相關(guān)\h14.7.2事件機(jī)制相關(guān)\h14.7.3負(fù)載均衡相關(guān)\h14.7.4統(tǒng)計相關(guān)\h14.8運行機(jī)制\h14.8.1模塊初始化\h14.8.2進(jìn)程初始化\h14.8.3基本參數(shù)初始化\h14.8.4epoll初始化\h14.8.5連接池初始化\h14.8.6監(jiān)聽端口初始化\h14.8.7初始化流程圖\h14.8.8添加事件\h14.8.9刪除事件\h14.8.10處理事件\h14.8.11接受連接\h14.8.12負(fù)載均衡\h14.8.13避免阻塞\h14.9總結(jié)\h第15章Nginx多線程機(jī)制\h15.1eventfd系統(tǒng)調(diào)用\h15.2pthread系統(tǒng)調(diào)用\h15.2.1pthread_create\h15.2.2pthread_exit\h15.3結(jié)構(gòu)定義\h15.3.1ngx_thread_task_t\h15.3.2ngx_thread_pool_queue_t\h15.3.3ngx_thread_pool_t\h15.3.4結(jié)構(gòu)關(guān)系圖\h15.4事件通知\h15.4.1函數(shù)接口\h15.4.2初始化\h15.4.3發(fā)送通知\h15.4.4處理通知\h15.5運行機(jī)制\h15.5.1完成任務(wù)隊列\(zhòng)h15.5.2創(chuàng)建線程池\h15.5.3創(chuàng)建任務(wù)\h15.5.4投遞任務(wù)\h15.5.5執(zhí)行任務(wù)\h15.5.6任務(wù)完成回調(diào)\h15.5.7銷毀線程池\h15.6在模塊里使用多線程\h15.6.1模塊設(shè)計\h15.6.2配置信息類\h15.6.3業(yè)務(wù)邏輯類\h15.6.4測試驗證\h15.7總結(jié)\h第16章NginxStream機(jī)制\h16.1模塊體系\h16.1.1函數(shù)指針表\h16.1.2基礎(chǔ)模塊\h16.1.3核心模塊\h16.1.4結(jié)構(gòu)關(guān)系圖\h16.1.5存儲模型\h16.2監(jiān)聽端口\h16.2.1結(jié)構(gòu)定義\h16.2.2解析配置\h16.2.3啟動監(jiān)聽\h16.3處理引擎\h16.3.1階段定義\h16.3.2函數(shù)原型\h16.3.3處理函數(shù)的存儲方式\h16.3.4引擎數(shù)據(jù)結(jié)構(gòu)\h16.3.5結(jié)構(gòu)關(guān)系圖\h16.3.6引擎的初始化\h16.4過濾引擎\h16.4.1函數(shù)原型\h16.4.2過濾函數(shù)鏈表\h16.5運行機(jī)制\h16.5.1會話結(jié)構(gòu)體\h16.5.2創(chuàng)建會話\h16.5.3執(zhí)行引擎\h16.5.4通用階段處理\h16.5.5預(yù)讀數(shù)據(jù)\h16.5.6產(chǎn)生響應(yīng)數(shù)據(jù)\h16.5.7過濾數(shù)據(jù)\h16.5.8結(jié)束會話\h16.6開發(fā)stream模塊\h16.6.1C++封裝\h16.6.2discard協(xié)議\h16.6.3time協(xié)議\h16.6.4chargen協(xié)議\h16.7總結(jié)\h第17章NginxHTTP機(jī)制\h17.1結(jié)構(gòu)定義\h17.1.1ngx_http_state_e\h17.1.2ngx_http_connection_t\h17.1.3ngx_http_request_t\h17.2初始化連接\h17.2.1建立連接\h17.2.2等待數(shù)據(jù)\h17.2.3讀取請求頭\h17.3執(zhí)行引擎\h17.3.1初始化引擎\h17.3.2通用階段\h17.3.3改寫階段\h17.3.4訪問控制階段\h17.3.5內(nèi)容產(chǎn)生階段\h17.4處理請求體\h17.4.1丟棄緩沖區(qū)數(shù)據(jù)\h17.4.2讀取并丟棄數(shù)據(jù)\h17.4.3讀事件處理函數(shù)\h17.4.4啟動丟棄處理\h17.5發(fā)送數(shù)據(jù)\h17.5.1發(fā)送初始化\h17.5.2事件處理函數(shù)\h17.6結(jié)束請求\h17.6.1釋放請求資源\h17.6.2檢查引用計數(shù)結(jié)束請求\h17.6.3檢查狀態(tài)結(jié)束請求\h17.6.4綜合處理結(jié)束請求\h17.7總結(jié)\h第18章Nginx與設(shè)計模式\h18.1設(shè)計模式簡介\h18.2框架級別的模式\h18.3業(yè)務(wù)級別的模式\h18.4代碼級別的模式\h18.5總結(jié)\h第19章OpenResty開發(fā)\h19.1簡介\h19.1.1歷史\h19.1.2版本\h19.1.3組成\h19.1.4性能\h19.1.5安裝\h19.1.6目錄結(jié)構(gòu)\h19.1.7命令行工具\h19.1.8參考手冊\h19.2Lua語言\h19.2.1注釋\h19.2.2數(shù)據(jù)類型\h19.2.3變量\h19.2.4運算\h19.2.5語句\h19.2.6函數(shù)\h19.2.7表\h19.2.8標(biāo)準(zhǔn)庫\h19.2.9模塊\h19.3LuaJIT\h19.3.1continue\h19.3.2bit\h19.3.3ffi\h19.4Lua模塊\h19.4.1指令簡介\h19.4.2配置指令\h19.4.3功能指令\h19.4.4指令關(guān)系圖\h19.4.5應(yīng)用開發(fā)流程\h19.5功能接口\h19.5.1運行日志\h19.5.2時間與日期\h19.5.3變量\h19.5.4正則表達(dá)式\h19.5.5請求處理\h19.5.6請求轉(zhuǎn)發(fā)\h19.5.7子請求\h19.5.8定時器\h19.5.9共享內(nèi)存\h19.6應(yīng)用實例\h19.6.1處理請求\h19.6.2過濾請求\h19.6.3轉(zhuǎn)發(fā)請求\h19.6.4子請求\h19.7StreamLua模塊\h19.7.1功能接口\h19.7.2discard\h19.7.3time\h19.7.4chargen\h19.7.5echo\h19.8lua-resty庫\h19.8.1core\h19.8.2cjson\h19.8.3redis\h19.9總結(jié)\h第20章結(jié)束語\h20.1本文的遺憾\h20.2下一步\h20.3臨別贈言\h附錄A推薦書目\h附錄BGDB調(diào)試簡介\h附錄CNginxC++模塊簡介\h附錄DNginx的字符串格式化\h附錄EnginScript簡介第0章導(dǎo)讀0.1關(guān)于本文Nginx{L-End}是由俄羅斯工程師IgorSysoev開發(fā)的一個高性能Web服務(wù)器,應(yīng)用于諸多頂級互聯(lián)網(wǎng)公司,為全世界數(shù)以億計的網(wǎng)民提供著出色的服務(wù)。根據(jù)某些權(quán)威公司分析統(tǒng)計,現(xiàn)在它已是市場份額第二大的Web服務(wù)器,并且仍然在快速增長,在Top1000的網(wǎng)站中更是超過了Apache而榮登榜首。除了最引人注目的高性能和高穩(wěn)定性外,Nginx的另一個突出特點是高擴(kuò)展性,其靈活優(yōu)秀的模塊化架構(gòu)允許在不修改核心的前提下增加任意功能。自2004年正式發(fā)布以來,Nginx已經(jīng)擁有了百余個官方及非官方的功能模塊(如proxy、rtmp、memcached、redis、mysql、lua等),這使得Nginx超越了一般意義上的Web服務(wù)器,成為了一個近乎“全能”的應(yīng)用服務(wù)器。Nginx功能強(qiáng)大,架構(gòu)復(fù)雜,學(xué)習(xí)、維護(hù)和開發(fā)的門檻都很高,導(dǎo)致很多初學(xué)者“久仰大名”但卻難以入門。本文將深入淺出地解析Nginx源碼,詳細(xì)講解如何使用C、C++和Lua語言來增強(qiáng)擴(kuò)展Nginx,并充分利用C++和Lua的高級特性,讓讀者能夠更加便捷、輕松地開發(fā)和定制Nginx,應(yīng)用到自己的實際工作中。0.2讀者對象本文適合以下各類讀者:■基于Nginx進(jìn)行二次開發(fā)的軟件工程師;■基于Openresty/Lua進(jìn)行二次開發(fā)的軟件工程師;■Nginx運維工程師;■Web服務(wù)器開發(fā)者;■對Nginx架構(gòu)、內(nèi)部實現(xiàn)感興趣的程序員;■C/C++/Lua、計算機(jī)編程的愛好者和在校學(xué)生。Nginx采用進(jìn)程池、事件驅(qū)動等方式來支持海量并發(fā)連接的處理,搭建了一個高性能高穩(wěn)定性的服務(wù)器框架,在這個框架之內(nèi)可以利用Nginx內(nèi)部的各種構(gòu)件編寫模塊,自由實現(xiàn)所需的業(yè)務(wù)功能。因此,國內(nèi)外都有很多個人和企業(yè)以Nginx為平臺進(jìn)行二次開發(fā),編寫模塊甚至直接定制Nginx,進(jìn)而提高網(wǎng)站的整體服務(wù)能力。本文由淺入深地詳細(xì)介紹了Nginx模塊開發(fā)的全過程,并且細(xì)致地分析了Nginx的內(nèi)部運行機(jī)制,能夠幫助軟件工程師較快地熟悉Nginx原理,迅速地投入到實際開發(fā)工作中。OpenResty是由OpenResty社區(qū)(創(chuàng)始人agentzh)維護(hù)的一個服務(wù)器開發(fā)包,核心組件是Nginx和ngx_lua模塊,可以在Nginx框架內(nèi)使用動態(tài)腳本語言Lua快捷實現(xiàn)業(yè)務(wù)邏輯,它既保持了Nginx高性能的優(yōu)勢,又沒有C語言開發(fā)效率低的劣勢,是目前服務(wù)器開發(fā)領(lǐng)域里的新生力量,前途不可限量。本文詳細(xì)介紹了OpenResty開發(fā)相關(guān)的各個方面知識,即使是沒有C語言基礎(chǔ)的開發(fā)者也可以很快理解掌握,開發(fā)出高質(zhì)量的網(wǎng)絡(luò)服務(wù)程序。Nginx項目十分活躍,版本更新較快,新的功能不斷增加,這使得市面上的相關(guān)書籍和網(wǎng)絡(luò)資料常常會變得“過時”——只言片語、語焉不詳或者答非所問{L-End},Nginx運維工程師很可能會遇到運行、配置出現(xiàn)問題卻無法解決的尷尬局面。然而Nginx是開源的,一切問題都可以在源碼中找到答案。但十余萬行的Nginx源碼又有如汪洋大海,如果沒有經(jīng)驗豐富的引航員指路,工程師難免會迷失方向,上下求索而不得。本文正是擔(dān)當(dāng)了這樣的引航員角色,詳盡地分析了Nginx的配置解析功能和HTTP/TCP/UDP處理流程,讓運維工程師可以快速定位配置指令和它的實現(xiàn)邏輯,深層次地做好Nginx的運維工作。對于那些自行開發(fā)Web服務(wù)器的程序員來說,Nginx也是一個非常有意義的借鑒品。它采用epoll/kqueue等異步調(diào)用削減了系統(tǒng)成本,充分挖掘了計算機(jī)硬件的性能,讓CPU、磁盤、網(wǎng)卡等設(shè)備并發(fā)運行,比傳統(tǒng)的多進(jìn)程、多線程方式的服務(wù)器運行得更快,服務(wù)能力更強(qiáng)。本文深入剖析Nginx源碼,解析了模塊架構(gòu)、進(jìn)程模型、事件驅(qū)動、多線程等機(jī)制,學(xué)習(xí)借鑒這些大師級、教科書級的經(jīng)典代碼,無疑會讓自己的開發(fā)功力更上一層樓,寫出更好的軟件產(chǎn)品。雖然Nginx功能如此強(qiáng)大,但它的實現(xiàn)卻非常清晰易讀:文件組織良好,代碼格式優(yōu)美,內(nèi)部隱藏的大量編程技巧、設(shè)計思想和架構(gòu)更是值得仔細(xì)研究的無價之寶。對于每一位喜好編程、準(zhǔn)備或者正在投身于軟件/互聯(lián)網(wǎng)行業(yè)的人來說,本文都是一個很好的起點,可以從零起步窺探到Nginx內(nèi)部的真正精髓,學(xué)習(xí)到各種實用的技術(shù)和知識,增加自身的“含金量”。本文還大量應(yīng)用了C++11標(biāo)準(zhǔn)和Boost程序庫,使用了lambda表達(dá)式、模板元編程等許多高級特性,可以看作是現(xiàn)代C++編程范式的一次成功實踐,讀者可以接觸到當(dāng)前C++最新、最前沿的技術(shù)。0.3讀者要求本文要求讀者基本了解C語言和網(wǎng)絡(luò)編程知識。Nginx本身是用C實現(xiàn)的,而本文主要使用C++作為編程語言,所以讀者應(yīng)該具備足夠的C/C++知識,例如宏、指針、類型轉(zhuǎn)換、封裝、繼承、異常等C/C++特性,如果已有實際編程經(jīng)驗則更好。在基本的C++之上,本文還使用了C++11標(biāo)準(zhǔn)和Boost程序庫來提高開發(fā)效率,要求讀者對模板、泛型編程和C++標(biāo)準(zhǔn)庫有一定的了解,能夠運用vector、list等常見的泛型容器和迭代器。如果讀者主要使用OpenResty/Lua開發(fā),那么可以不必過多關(guān)心C++,但基本的C語言知識還是必須的,可以更好地理解Nginx/OpenResty的工作原理。Nginx是一個Web服務(wù)器,所以熟悉網(wǎng)絡(luò)編程對于學(xué)習(xí)本文是非常有益的。但由于Nginx封裝了很多網(wǎng)絡(luò)通信的底層細(xì)節(jié),所以本文不要求讀者對網(wǎng)絡(luò)編程技術(shù)有很深刻的認(rèn)識,但至少應(yīng)該對TCP和HTTP通信協(xié)議有所了解。此外,因為Nginx大多運行在Linux服務(wù)器上,讀者還應(yīng)該再學(xué)習(xí)一些UNIX/Linux和Shell編程的相關(guān)知識,才能夠編寫Nginx的編譯腳本和運行維護(hù)。附錄A列出了一些技術(shù)書籍,涵蓋了大部分本文要求掌握的C/C++語言和網(wǎng)絡(luò)編程技術(shù)知識,建議讀者閱讀本文時參考。0.4運行環(huán)境Nginx可以跨平臺編譯和運行,支持Linux、FreeBSD、macOS、Windows等多種操作系統(tǒng)。但就目前市場來看,Linux是應(yīng)用最普及的服務(wù)器操作系統(tǒng),故本文的開發(fā)環(huán)境選用Linux。Linux有很多的發(fā)行版本,企業(yè)中使用較多的是偏重于穩(wěn)定性的CentOS和偏重于易用性的Ubuntu,出于個人喜好的原因本文選擇了后者(請CentOS支持者見諒)。下面是本文使用的具體環(huán)境:■操作系統(tǒng):Ubuntu14.04.05(Linux4.4.0);■Shell:系統(tǒng)自帶的dash(注意不是bash);■編譯器:系統(tǒng)自帶的GCC4.8.4(支持C++11標(biāo)準(zhǔn))。0.5本文的結(jié)構(gòu)Nginx是一個非常龐大的系統(tǒng),內(nèi)部結(jié)構(gòu)錯綜復(fù)雜,簡單的循序漸進(jìn)方式難以透徹地講解清楚,也不利于學(xué)習(xí)和掌握開發(fā)知識,所以本文結(jié)合“知其所以然”再“知其然”的方式組織全書的章節(jié):首先介紹Nginx的基本知識作為入門,然后由淺入深地解析Nginx的源碼和架構(gòu),理解了內(nèi)部運行機(jī)制后再介紹如何開發(fā)定制Nginx。學(xué)習(xí)Nginx不研究其內(nèi)部工作原理是不行的,但解析得太深會導(dǎo)致源碼太多,文字過于晦澀難懂;介紹得太淺又不能達(dá)到“知其所以然”的效果。所以本文只以中等深度研究Nginx源碼和框架,講解關(guān)鍵的流程、原理和函數(shù)調(diào)用,不涉及過于底層的實現(xiàn)細(xì)節(jié)。每個章節(jié)首先學(xué)習(xí)結(jié)構(gòu)定義等靜態(tài)模型,然后配合圖示研究工作原理、運行機(jī)制等動態(tài)模型,最后結(jié)合Nginx官方源碼,通過實例講解開發(fā)要點,這種方式能夠較好地覆蓋Nginx開發(fā)的各個方面。全書共20章,大致可分為四部分:第1章是入門知識,簡要介紹Nginx的安裝和使用;第2章至第12章重點講解使用C/C++語言開發(fā)定制Nginx,主要是“知其然”;第13章至第18章則深入Nginx的內(nèi)部,剖析它的底層運行機(jī)制,幫助讀者深層次地理解Nginx,是“知其所以然”;第19章專門介紹OpenResty,它可以用Lua語言快速開發(fā)出高性能的Web應(yīng)用。各章的內(nèi)容簡介如下?!龅?章:Nginx入門簡要介紹Nginx的歷史和特點,以及如何編譯、安裝和配置Nginx,可以當(dāng)作是一本濃縮精華的Nginx使用手冊?!龅?章:Nginx開發(fā)準(zhǔn)備本章是開發(fā)Nginx模塊前的準(zhǔn)備工作,介紹本文使用的C++11標(biāo)準(zhǔn)和Boost程序庫,還有Nginx源碼的目錄結(jié)構(gòu)、基本的代碼風(fēng)格和特點。針對Nginx源碼的特點提出了C++的解決方案,實現(xiàn)了一個對Nginx數(shù)據(jù)結(jié)構(gòu)的C++封裝類。■第3章:Nginx基礎(chǔ)設(shè)施剖析Nginx這樣復(fù)雜的系統(tǒng)必須從最底層的基礎(chǔ)設(shè)施開始,本章首先介紹了Nginx框架里基本的整數(shù)類型和錯誤碼,然后再研究內(nèi)存池、字符串、時間日期和運行日志,同時使用C++11標(biāo)準(zhǔn)進(jìn)行了面向?qū)ο蟮姆庋b,打造出方便易用的基礎(chǔ)工具類?!龅?章:Nginx高級數(shù)據(jù)結(jié)構(gòu)本章研究ngx_array_t、ngx_list_t、ngx_queue_t、ngx_buf_t、ngx_rbtree_t等各種高級Nginx數(shù)據(jù)結(jié)構(gòu),它們類似C++的標(biāo)準(zhǔn)容器,在Nginx框架里經(jīng)常出現(xiàn),必須很好地理解并掌握它們的特性和用法,C++封裝能夠讓這些數(shù)據(jù)結(jié)構(gòu)更容易使用。■第5章:Nginx開發(fā)綜述本章使用一個簡單的例子介紹Nginx開發(fā)的基本流程,并講解了如何編寫模塊集成腳本?!龅?章:Nginx模塊體系本章詳細(xì)剖析Nginx的模塊架構(gòu)和配置解析原理,這是Nginx開發(fā)必需的重要技術(shù),也是理解Nginx架構(gòu)的關(guān)鍵,最后實現(xiàn)了C++封裝類,開發(fā)出現(xiàn)代C++風(fēng)格的Nginx模塊?!龅?章:NginxHTTP框架綜述本章深入研究Nginx的HTTP處理框架,解析http模塊的核心工作原理和流程,包括處理階段、處理引擎、過濾鏈表等重要概念?!龅?章:NginxHTTP請求處理本章詳細(xì)解析ngx_http_request_t結(jié)構(gòu),講解請求頭、請求體、響應(yīng)頭、響應(yīng)體等數(shù)據(jù)成員和它們的操作方法,實現(xiàn)Nginx里最常用的handler模塊和filter模塊?!龅?章:NginxHTTP請求轉(zhuǎn)發(fā)本章解析Nginx的請求轉(zhuǎn)發(fā)機(jī)制,它是Nginx反向代理的基礎(chǔ),實現(xiàn)轉(zhuǎn)發(fā)請求的upstream模塊和負(fù)載均衡的load-balance模塊,訪問外部的網(wǎng)絡(luò)資源。■第10章:NginxHTTP子請求本章講解Nginx的子請求機(jī)制,可以讓Nginx像調(diào)用函數(shù)那樣調(diào)用location里的功能,發(fā)起多個子請求實現(xiàn)復(fù)雜的業(yè)務(wù)邏輯,讓Nginx變成一臺強(qiáng)大的應(yīng)用服務(wù)器?!龅?1章:Nginx變量Nginx內(nèi)置非常靈活的變量機(jī)制,是配置指令之外另一種與模塊通信的方式,增強(qiáng)了靜態(tài)的配置文件與動態(tài)運行的模塊之間的互操作性。本章剖析了變量機(jī)制的工作原理,實現(xiàn)了易用的C++封裝類?!龅?2章:Nginx輔助設(shè)施本章介紹Nginx提供的一些實用工具,包括MD5/SHA-1摘要、CRC/Base64/URI編解碼、正則表達(dá)式、共享內(nèi)存等,它們是并發(fā)處理和協(xié)議解析之外實現(xiàn)一個完善的Web服務(wù)器所必需的輔助功能?!龅?3章:Nginx進(jìn)程機(jī)制Nginx使用了進(jìn)程池模式,以一個master進(jìn)程管理多個worker進(jìn)程,可以充分地利用多核CPU。本章先介紹基本的UNIX系統(tǒng)調(diào)用,然后配合圖解詳細(xì)研究Nginx的信號處理、啟動過程、單進(jìn)程和多進(jìn)程的工作流程及要點?!龅?4章:Nginx事件機(jī)制事件驅(qū)動機(jī)制是Nginx高性能的關(guān)鍵,本章詳細(xì)闡述socket系統(tǒng)調(diào)用、epoll工作原理、事件模塊體系和相關(guān)的數(shù)據(jù)結(jié)構(gòu)、使用多幅流程圖完整解析了連接池、監(jiān)聽端口、接受連接、處理網(wǎng)絡(luò)和定時器事件、負(fù)載均衡等Nginx的核心功能?!龅?5章:Nginx多線程機(jī)制Nginx主要使用單線程加事件驅(qū)動,但也對多線程提供了有限的支持,本章介紹Nginx多線程機(jī)制的工作原理:線程池+生產(chǎn)者/消費者,還給出了一個實際的開發(fā)示例?!龅?6章:NginxStream機(jī)制Nginx從1.9.0開始引入了Stream框架,支持直接處理TCP/UDP協(xié)議,相當(dāng)于是一個簡化版的HTTP框架,研究它可以更好地理解進(jìn)程機(jī)制和事件機(jī)制在處理請求時的作用。本章解析Stream機(jī)制的模塊體系和運行機(jī)制,并實現(xiàn)了discard、time等基本的應(yīng)用協(xié)議?!龅?7章:NginxHTTP機(jī)制本章是第7章的進(jìn)階內(nèi)容,結(jié)合事件機(jī)制,使用源碼輔以流程圖,詳細(xì)介紹HTTP框架的關(guān)鍵運行機(jī)制,包括初始化連接、階段式處理引擎、讀取數(shù)據(jù)、發(fā)送數(shù)據(jù)和結(jié)束請求等?!龅?8章:Nginx與設(shè)計模式本章綜合之前章節(jié)的內(nèi)容,簡要總結(jié)了在Nginx里應(yīng)用的一些設(shè)計模式,幫助讀者從設(shè)計模式的角度來進(jìn)一步理解Nginx架構(gòu)?!龅?9章:OpenResty開發(fā)OpenResty是一個“比Nginx更好的Nginx”,它集成了眾多優(yōu)良的Nginx模塊和庫,可以用動態(tài)語言Lua快速開發(fā)出高質(zhì)量高性能的Web應(yīng)用。本章介紹了OpenResty相關(guān)的各方面知識,包括Lua語言、LuaJIT、配置指令、功能接口和開發(fā)示例,而且完全從零起步,編程初學(xué)者也可以較容易地掌握這些知識?!龅?0章:結(jié)束語本章給出了讀者在閱讀完本文后進(jìn)一步學(xué)習(xí)研究Nginx的方向?!龈戒洉┑母戒浭菍Ρ疚恼牡难a(bǔ)充,列出了一些參考書籍,還有就是一些不宜放在正文里的比較瑣碎的內(nèi)容,比如ngx_cpp_module介紹、ngx_sprintf()格式列表等。值得一提的是特別介紹了nginScript,可以使用JavaScript腳本靈活地定制Nginx。0.6如何閱讀本文編程初學(xué)者或者初次接觸Nginx的讀者應(yīng)當(dāng)首先閱讀第1章,了解什么是Nginx,并在本文的指導(dǎo)下安裝配置Nginx,搭建自己的開發(fā)環(huán)境,然后學(xué)習(xí)后續(xù)章節(jié)。對Nginx比較熟悉的讀者可以跳過第1章,從第2章開始順序閱讀,以Nginx源碼片段為出發(fā)點,學(xué)習(xí)如何使用C/C++來開發(fā)Nginx模塊。其中第2章至第4章是C/C++開發(fā)的基礎(chǔ),第5章才能開始正式編寫Nginx模塊。如果讀者已經(jīng)是一個比較熟練的Nginx開發(fā)者,那么可以直接閱讀第5、6章及之后的章節(jié),鉆研Nginx的內(nèi)部架構(gòu)和實現(xiàn)原理,深入理解Nginx的運行機(jī)制。不過第2章至第4章也并非可以完全忽略,其中的C++泛型、元編程等嶄新的編程范式也許會讓你眼前一亮,能夠從一個全新的角度來審視Nginx。使用純C語言開發(fā)的讀者可以忽略書中標(biāo)題含有“C++”的小節(jié),而只閱讀與NginxC接口、源碼相關(guān)的部分。如果讀者只想使用OpenResty/Lua開發(fā)Nginx應(yīng)用,建議先閱讀第1章,了解Nginx安裝部署的基本知識,然后跳過之后的Nginx框架源碼解析,直接閱讀第19章,快速開始OpenResty的學(xué)習(xí)。不過還是希望讀者有了一些實際經(jīng)驗后再回頭研究前面的章節(jié),只有深入理解Nginx內(nèi)部細(xì)節(jié),才能更好地開發(fā)OpenResty應(yīng)用。0.7本文的源碼為方便讀者利用本文學(xué)習(xí)研究Nginx和OpenResty,作者在GitHub網(wǎng)站上發(fā)布了本文內(nèi)所有C/C++、OpenResty示例程序和Shell腳本的源代碼,地址是:第1章Nginx入門Nginx是一個高性能、高穩(wěn)定性和高擴(kuò)展性的輕量級TCP、UDP、HTTP、反向代理和郵件代理服務(wù)器。它運行效率高,系統(tǒng)消耗低,使用操作系統(tǒng)提供的異步I/O調(diào)用可以無阻塞地處理上萬的并發(fā)請求,是當(dāng)今眾多Web服務(wù)器中的佼佼者,被Airbnb、Dropbox、GitHub、Hulu、WordPress等許多知名網(wǎng)站所采用。本章簡要介紹Nginx的歷史和特點,講解如何在Linux上安裝和配置Nginx,幫助讀者盡快熟悉Nginx。1.1關(guān)于Nginx自20世紀(jì)90年代以來,Internet和WorldWideWeb逐漸在全世界普及。早期并沒有Web服務(wù)器的概念,Internet上的資源只是一些簡單的靜態(tài)文件。慢慢地,Web服務(wù)器出現(xiàn)了,它在用戶和文件之間加入了一個中間層,響應(yīng)用戶的HTTP請求,從本地或者其他地方獲取對應(yīng)的資源,再返回給用戶。1995年,著名的Apache誕生了。最開始它只是一個NCSAHTTPd服務(wù)器的修改版,但許多志愿者不停地為它添加補(bǔ)丁新增功能,使它迅速成為了那個年代最流行的Web服務(wù)器,甚至直到二十多年后的今天也是如此。由于時代的限制,Apache被設(shè)計為“重量級”的服務(wù)器,使用fork進(jìn)程的方式響應(yīng)HTTP請求。雖然近年來Apache增加了多線程、多核心等新特性,但基本架構(gòu)無法改變,在動輒成千上萬并發(fā)的情況下顯得有些力不從心,性能嚴(yán)重下降。本世紀(jì)初,隨著C10K問題的提出{L-End},計算機(jī)界開始認(rèn)真地研究Web服務(wù)器的開發(fā)模型。Linux、FreeBSD等操作系統(tǒng)引入了epoll、kqueue等高效異步I/O接口,奠定了解決海量并發(fā)的C10K甚至C100K問題的基礎(chǔ),最終導(dǎo)致Nginx這個Web服務(wù)器新秀的出現(xiàn)。1.1.1歷史2002年,在仔細(xì)研究了已有的Web服務(wù)器之后,當(dāng)時任職于俄羅斯門戶網(wǎng)站Rambler的工程師IgorSysoev開始編寫一個新的Web服務(wù)器,目標(biāo)是解決高并發(fā)的C10K問題,并設(shè)計了完全不同于以往服務(wù)器的全新架構(gòu)——這就是Nginx。2004年,Nginx正式開源,版本號為0.1.0,由于其優(yōu)異的性能、絕佳的穩(wěn)定性和良好的擴(kuò)展性等鮮明特點迅速吸引了大量關(guān)注。在開源大旗的鼓舞之下,無數(shù)開發(fā)者加入貢獻(xiàn)行列,為它修復(fù)錯誤、編寫功能模塊,Nginx從此踏上了迅猛發(fā)展的道路,從當(dāng)初默默無聞的小卒成長為如今Web服務(wù)器界的巨人。2011年,Nginx之父IgorSysoev在舊金山正式成立公司,為Nginx提供商業(yè)服務(wù),并發(fā)布了商業(yè)版本的NginxPlus。1.1.2特點作為Web服務(wù)器的后起之秀,Nginx能夠戰(zhàn)勝Apache、Lighttpd、Jetty、Tomcat等眾多對手,獲得頂級互聯(lián)網(wǎng)公司的青睞,必然有它的獨到之處。以開發(fā)者的視角來看,Nginx的特點是:■高性能卓越的性能是Nginx最突出的特點。Nginx完全使用C語言編寫,采用事件驅(qū)動模型,并且有針對性地對操作系統(tǒng)進(jìn)行了特別優(yōu)化,可以無阻塞地處理海量并發(fā)連接,經(jīng)過仔細(xì)調(diào)整配置參數(shù)還能夠進(jìn)一步釋放潛力,幫助網(wǎng)站應(yīng)對日益增長的巨大訪問壓力。■高穩(wěn)定性高度的穩(wěn)定性是Nginx的又一大特點。內(nèi)存池避免了C程序常見的資源泄漏問題,模塊化的架構(gòu)使得各個功能模塊完全解耦,消除了相互間可能造成的不良影響,而獨特的onemaster/multiworkers進(jìn)程池設(shè)計則實現(xiàn)了自我監(jiān)控和管理,保證即使worker進(jìn)程發(fā)生嚴(yán)重錯誤也可以快速恢復(fù)。在實際應(yīng)用中,Nginx服務(wù)器一經(jīng)啟動,就可以穩(wěn)定地運行數(shù)天甚至數(shù)月之久。■低資源消耗Nginx的代碼質(zhì)量極高,不使用傳統(tǒng)的進(jìn)程或線程服務(wù)器模型,沒有進(jìn)程或線程切換時的成本,而且它還使用了很多節(jié)約系統(tǒng)資源的編程技巧,例如使用accept4來減少內(nèi)核調(diào)用的次數(shù)、使用writev集中發(fā)送數(shù)據(jù)、使用字符串引用而不是拷貝,可以把寶貴的CPU和內(nèi)存資源更多地用于對外提供服務(wù),提高并發(fā)支持能力。■高擴(kuò)展性Nginx的模塊化架構(gòu)是一個非凡的設(shè)計。Nginx本身就是由各種位于不同層次的功能模塊組合而成的,它也允許/鼓勵任何人依據(jù)架構(gòu)規(guī)范開發(fā)任意功能的模塊——同時充分利用Nginx框架提供的各種高效機(jī)制,然后再完美地融合到Nginx之中?;诟邤U(kuò)展性,Nginx以模塊的形式實現(xiàn)了豐富的功能,例如access、flv、gzip、proxy、ssl等,而廣大開發(fā)者也編寫了大量的第三方模塊,實現(xiàn)了更多更有用的功能。這些模塊都遵循一致的開發(fā)原則,可以在配置文件里靈活配置,讓Nginx提供更好的網(wǎng)絡(luò)服務(wù)。{L-End}以上的三高一低四個方面是從開發(fā)者的角度總結(jié)的Nginx的主要特點。當(dāng)然Nginx的優(yōu)勢遠(yuǎn)不止這些,它還能夠運行在多種操作系統(tǒng)上,安裝和配置都很容易,支持定制日志、平滑升級、策略限速、熱部署等許多重要的運維功能。高性能是品質(zhì),高穩(wěn)定性是保障,低資源消耗是基石,而高擴(kuò)展性則是Nginx生命力的源泉,使Nginx擁有了近乎“無限”的能力——如果現(xiàn)有的Nginx模塊不能滿足我們的需求,最佳的解決方案無疑是開發(fā)自己的模塊,集成到Nginx里,在享受Nginx高性能、高穩(wěn)定性的同時實現(xiàn)自己的業(yè)務(wù)邏輯。這正是作者撰寫本文的目的。1.1.3進(jìn)程模型Nginx采用了獨特的onemaster/multiworkers進(jìn)程池機(jī)制,它是Nginx能夠穩(wěn)定運行、靈活配置的保證。通常情況下,Nginx會啟動一個master進(jìn)程和多個worker進(jìn)程對外提供服務(wù){(diào)L-End}。master進(jìn)程又稱監(jiān)控進(jìn)程,它并不處理具體的TCP/HTTP請求,只接收UNIX信號,管理和監(jiān)控worker進(jìn)程,所以工作比較“清閑”。worker進(jìn)程平等地競爭accept客戶端的連接,執(zhí)行Nginx主要的業(yè)務(wù)邏輯,使用epoll、kqueue等機(jī)制高效率地處理TCP/HTTP請求。master進(jìn)程和worker進(jìn)程使用操作系統(tǒng)提供的進(jìn)程間通信機(jī)制——如信號、UNIX域套接字、共享內(nèi)存等互相通信,彼此獨立又保持一定的聯(lián)系,形成一個有機(jī)的整體。當(dāng)某個worker進(jìn)程發(fā)生錯誤意外中止時,master進(jìn)程會快速重新fork出新的worker進(jìn)程,保持進(jìn)程池的穩(wěn)定(具體工作原理可參見第13章)。Nginx的進(jìn)程模型如圖1-1所示。圖1-1Nginx的進(jìn)程模型在多核心的服務(wù)器上,Nginx可以配置為每個進(jìn)程運行在單獨的核心,最大限度地減少CPU進(jìn)程切換的成本,提高系統(tǒng)運行效率。Nginx也可以配置為不使用master進(jìn)程,只有一個worker進(jìn)程提供服務(wù),這種方式不適用于真正的生產(chǎn)環(huán)境,但對于開發(fā)測試卻很有用。1.1.4版本本文不討論商業(yè)版本的NginxPlus{L-End},只討論開源版本的Nginx,它的官網(wǎng)是:http:///。Nginx官網(wǎng)提供三種類型的版本供用戶選擇:■Mainline:主線開發(fā)版本,版本號為奇數(shù)。更新速度很快,差不多每個月都會發(fā)布新版本,匯集了最新的功能和錯誤修復(fù),但穩(wěn)定性可能略差?!鯯table:當(dāng)前的穩(wěn)定版本,版本號為偶數(shù)。由Mainline版本fork而來,經(jīng)過了完全測試,代碼有一年的“凍結(jié)”期,除非有重要Bug修復(fù)否則不會變動,建議在正式生產(chǎn)環(huán)境中使用?!鯨egacy:歷年曾經(jīng)發(fā)布的穩(wěn)定版本,有特殊需求的話可以采用。這三個版本的關(guān)系可以用圖1-2來表示。圖1-2Mainline、Stable、Legacy三個版本的關(guān)系本文采用的Nginx是2017年4月發(fā)布的Stable1.12.0版,由于Nginx的核心架構(gòu)和代碼一直都比較穩(wěn)定(但局部實現(xiàn)偶爾會變動),所以書中的討論也基本適用于較早期的各種版本,對于部分重要的版本差異會加以特別注解。1.2安裝Nginx本節(jié)介紹在Linux操作系統(tǒng)上使用源碼包的方式安裝Nginx,但并不是一個完全的安裝部署手冊,僅供讀者參考。{L-End}1.2.1準(zhǔn)備工作只要系統(tǒng)里有GCC(或其他C編譯器),Nginx就可以編譯安裝,但幾個基本且重要的功能依賴于第三方庫:■zlib:實現(xiàn)gzip壓縮解壓縮功能。■pcre:實現(xiàn)配置文件里的正則表達(dá)式解析功能?!鰋penssl:實現(xiàn)SSL功能。在Ubuntu里安裝這些依賴庫的命令是:使用其他操作系統(tǒng)的讀者請參考網(wǎng)絡(luò)相關(guān)資料,例如對于CentOS,安裝的命令可以是:1.2.2快速安裝Nginx主要以源碼的方式發(fā)布,可以從官網(wǎng)上直接下載源碼形式的安裝包:這是最簡單的Nginx安裝方式,沒有任何的定制參數(shù)。Nginx將會安裝到默認(rèn)的“/usr/local/nginx/”目錄,可執(zhí)行文件是“/usr/local/nginx/sbin/nginx”,默認(rèn)配置文件是“/usr/local/nginx/conf/nginx.conf”。1.2.3運行命令啟動和停止Nginx需要以root身份,或者使用sudo。下面介紹一些常用但不是全部的Nginx命令,更詳細(xì)的命令說明可以使用-h/-?參數(shù)查看,或者查閱網(wǎng)絡(luò)資料。不帶參數(shù)簡單地執(zhí)行程序就可以啟動Nginx服務(wù),這將使用默認(rèn)的配置文件:我們也可以使用-c參數(shù)指定配置文件,這種方式允許啟動多個不同的Nginx實例:-ppath是-c的增強(qiáng)版,用來設(shè)置工作目錄,可以指定完整的Nginx環(huán)境:-ssignal參數(shù)可以快速地停止或者重啟Nginx,signal值可以是stop、quit、reload或reopen:需要注意的是,如果使用-c/-p參數(shù)啟動了Nginx,那么在使用-s時也必須使用-c/-p參數(shù),告訴Nginx使用的是哪個配置文件,否則會運行失敗。例如:-t或-T參數(shù)可以測試配置文件是否正確,后者同時還會打印出文件內(nèi)容方便檢查:-v或-V參數(shù)可以顯示Nginx的版本信息,它不需要root權(quán)限,兩者的區(qū)別是-V可以顯示更多的信息,包括GCC版本、操作系統(tǒng)版本、configure參數(shù)等定制信息:-V參數(shù)很多時候特別有用,由于它給出了編譯Nginx時的全部相關(guān)信息,所以我們可以使用其他版本的源碼(例如升級或者修復(fù)Bug)加上這些參數(shù)重新編譯出一個功能完全相同的新程序。1.2.4驗證安裝如果已經(jīng)成功啟動了Nginx服務(wù),那么就可以使用wget或者curl這樣的工具來驗證Nginx是否正常工作。Nginx的默認(rèn)配置文件開啟了localhost:80服務(wù),在/usr/local/nginx/html下存放有一些示例靜態(tài)html文件,curl測試命令是:如果Nginx正在運行,那么curl的部分輸出可能如下:使用Linux的ps命令配合grep可以看到所有Nginx進(jìn)程,也可以驗證Nginx是否正常運行:從ps的輸出我們可以看到當(dāng)前共有兩個Nginx進(jìn)程,其中進(jìn)程號為8261的是master進(jìn)程,而8262號進(jìn)程則是worker進(jìn)程。如果Nginx沒有正確運行,我們可以查看它的錯誤日志以排除故障,默認(rèn)的位置是“/usr/local/nginx/logs/error.log”。1.2.5定制安裝make前執(zhí)行的configure是Nginx的重要組成部件,它檢查各種系統(tǒng)參數(shù)、命令行參數(shù)和依賴庫,根據(jù)這些參數(shù)生成定制的Makefile和一些C源碼文件,沒有它就無法正確編譯安裝Nginx。雖然configure只是一個標(biāo)準(zhǔn)的Shell腳本,但其內(nèi)部邏輯十分復(fù)雜,為了支持各種操作系統(tǒng)、編譯器和CPU做了大量工作,復(fù)雜程度甚至不遜于Nginx自身的C程序。{L-End}由于configure的選項很多,本文不能也沒有必要完全羅列,僅列出一些個人認(rèn)為比較重要的選項,其他可參考help或者網(wǎng)絡(luò)資源。配置Nginx安裝部署的根目錄,也就是工作目錄。默認(rèn)值是“/usr/local/nginx/”,可以把它改為其他路徑,這樣就可以在一個系統(tǒng)里安裝多個不同用途的Nginx{L-End},類似的選項還有--sbin-path、--conf-path等。例如:啟用Nginx的stream模塊,讓Nginx能夠直接處理TCP/UDP協(xié)議。啟用Nginx的線程池機(jī)制,允許Nginx使用多線程來處理數(shù)據(jù)。雖然Linux系統(tǒng)通常都內(nèi)置PCRE、OpenSSL庫,但有的時候可能版本比較低,功能不完善(更嚴(yán)重的是有bug),所以可以用這兩個選項來指定PCRE、OpenSSL的源碼目錄,從而使用最新的版本,例如:這是一系列近百個模塊配置選項,用來決定在Nginx里啟用或者禁用哪些自帶的功能模塊,我們可以根據(jù)自身的實際情況來定制Nginx的功能,例如:-build=NAME:這個選項是Nginx1.7版之后增加的新功能,可以在Nginx的版本信息里加入自定義的字符串信息,比如公司名稱、構(gòu)建日期、源碼版本號等,讓nginx-v/-V更加可讀。例如,下面的配置命令為Nginx增加了構(gòu)建用戶名和構(gòu)建日期:這條命令在字符串里使用Shell直接執(zhí)行了date命令,并把結(jié)果輸出到了-build參數(shù)里,編譯后用Nginx-v查看版本信息是:這是一個對于我們研究Nginx非常有用的編譯選項,啟用了Nginx的調(diào)試模式,可以讓Nginx在運行日志里打印出更多的調(diào)試信息。這個選項用來指定編譯鏈接時的額外參數(shù),可以鏈接其他第三方庫,例如使用jemalloc來替代GCC的內(nèi)存分配函數(shù):這是Nginx高擴(kuò)展性的起點,是configure最重要的選項,指定第三方模塊的源碼路徑。這樣Nginx就可以把第三方模塊像自帶模塊一樣編譯進(jìn)可執(zhí)行文件(靜態(tài)鏈接),從而擴(kuò)展Nginx的能力。我們會在之后的5.1節(jié)看到它的詳細(xì)用法。需要注意的是,-add-module與其他選項不同,在configure命令行里可以出現(xiàn)任意次,為Nginx添加任意數(shù)量的第三方模塊。它是自Nginx1.9.11后新增加的選項,與-add-module功能基本相同,但可以把模塊編譯為*.so形式的動態(tài)庫,為Nginx添加了動態(tài)模塊的能力。-add-dynamic-module分離了Nginx主可執(zhí)行程序與模塊,可以在啟動時靈活組合動態(tài)加載,方便Nginx功能更新。它同時也能夠減少編譯的時間消耗,使用“makemodules”只編譯變動的模塊,而Nginx核心代碼則無需重新編譯。1.3配置Nginxconfigure是對Nginx的靜態(tài)配置,確定Nginx的基本運行環(huán)境和功能模塊,使用簡單的命令行參數(shù)就可以完成。但Nginx的配置絕不只有configure這么簡單,實際上,配置文件才是Nginx的核心,它與Nginx的模塊化架構(gòu)是一個互相依存的整體,決定了Nginx的進(jìn)程數(shù)量、運行日志、虛擬主機(jī)、反向代理、郵件代理、各種請求處理邏輯、優(yōu)化調(diào)整等方方面面,眾多的模塊都要依賴配置文件里的指令才能正常工作。Nginx在啟動時將會讀取配置文件,根據(jù)配置指令調(diào)用不同的模塊處理,設(shè)置它們的運行參數(shù)。由于本文作者并非運維方面的專家,故刪繁就簡,只介紹作者認(rèn)為與開發(fā)有關(guān)、比較常用的指令,有進(jìn)一步需要的讀者可參考官網(wǎng)Wiki或者其他相關(guān)資料。{L-End}1.3.1配置文件格式Nginx的配置文件是一個普通的純文本文件,使用了Nginx自定義的一套配置語法,更接近于腳本語言,混合了Shell、Perl和C的部分特性,要點敘述如下:■與Shell/Perl相同,使用#開始一個注釋行;■配置指令以分號結(jié)束,可以接受多個參數(shù),用空白字符分隔;■可以使用單引號或者雙引號來定義字符串,允許用“\”轉(zhuǎn)義字符;■配置指令和參數(shù)也可以用引號來指定,特別是當(dāng)它含有空格的時候;■配置塊(block)是特殊的配置指令,它有一個{...}參數(shù)且無須分號結(jié)束,{...}里面可以包含多個配置指令,相當(dāng)于C語言里的復(fù)合語句;■有的配置指令只能出現(xiàn)在特定的配置塊里(即語境Context);■配置塊里可以再包含配置塊,嵌套層次沒有限制,但需符合配置塊的語義;■可以使用include指令包含其他配置文件,支持“*”通配符,類似C語言;■使用$var可以引用預(yù)定義的一些變量,增加配置的靈活性;■不能識別或錯誤的配置指令會導(dǎo)致Nginx解析失敗,無法啟動。下面列出Nginx自帶的配置文件片段,部分較重要的配置指令用黑體表示:這個配置文件片段在全局域里出現(xiàn)了一個配置指令worker_processes,然后是兩個大配置塊:events和http,分別配置了event模塊和http模塊的行為。events配置塊很簡單,里面只有一個worker_connections指令,確定每個worker進(jìn)程可以處理的最大連接數(shù)。http配置塊比較復(fù)雜,它先用include包含了另一個配置文件mime.types,設(shè)置了默認(rèn)的MIME類型,然后使用server塊定義了一個端口為80的虛擬主機(jī)。server塊里又有兩個location塊,定義了訪問虛擬主機(jī)上不同路徑時的具體行為,在這里只指定了文檔根目錄和設(shè)置index文件。接下來我們就來了解一些常用的Nginx配置指令。1.3.2進(jìn)程配置以下六個進(jìn)程配置指令不屬于任何配置塊,只能在全局域(main)里配置。設(shè)置Nginx能夠啟動的worker進(jìn)程的數(shù)量,它直接影響Nginx的性能。通常當(dāng)worker數(shù)與服務(wù)器的CPU核心數(shù)相等時可以獲得最佳的性能,這時每一個worker都會工作在一個獨立的CPU核心上,完全消除CPU調(diào)度的成本(需配合worker_cpu_affinity指令)。worker_processes的默認(rèn)值是1。如果不清楚服務(wù)器的CPU核心數(shù)量,那么可以設(shè)置為auto參數(shù),Nginx會嘗試探測數(shù)量并設(shè)置。{L-End}決定是否啟用Nginx的進(jìn)程池機(jī)制,默認(rèn)值是on。如果設(shè)置為off,那么Nginx不會建立master進(jìn)程,只會用一個worker進(jìn)程處理請求,worker_processes指令也會失效,并發(fā)處理能力大大下降。在生產(chǎn)環(huán)境中不建議設(shè)置為off,但對于研究來說它很有用,可以簡化我們的調(diào)試工作。決定是否以守護(hù)進(jìn)程的方式運行Nginx,默認(rèn)值是on。大多數(shù)情況下Nginx應(yīng)該是一個守護(hù)進(jìn)程,運行在后臺,不與終端有任何的交互,也減少了無謂的資源消耗。但禁用守護(hù)進(jìn)程同樣有利于我們的研究調(diào)試,可以直接用cout或printf輸出調(diào)試信息,而不必去查看日志。本文中配置master_process為off,偶爾會配置daemonoff。指定worker進(jìn)程運行在某個CPU核心上,即CPU綁定,對于多核心的CPU來說可以減少CPU的切換,提高cache命中率,讓Nginx更充分地利用CPU資源。例如,如果在一個4核CPU上,可以設(shè)置如下:早期(1.9.10之前)我們只能使用掩碼的方式手工綁定,現(xiàn)在則可以使用auto參數(shù)讓Nginx自動綁定CPU。配置Nginx的工作目錄,實際上僅用來存放coredump文件,在Nginx發(fā)生意外崩潰時可以用gdb調(diào)試查找原因。這是1.11.11版新增的指令。當(dāng)使用“-squit”要求終止運行時,Nginx將最多等待time的時間,然后強(qiáng)制關(guān)閉進(jìn)程。它可以較好地解決系統(tǒng)里大量出現(xiàn)“isshuttingdown”狀態(tài)Nginx進(jìn)程的問題。1.3.3動態(tài)模塊配置Nginx在1.9.11后支持動態(tài)加載模塊,指令格式是:file參數(shù)標(biāo)記了模塊的文件名,可以指定絕對路徑,也可以用相對路徑,默認(rèn)查找路徑是安裝后的“/usr/local/nginx”目錄(即-prefix或-p指定的路徑),例如:注意load_module指令只能在全局域里配置,而且必須在events、stream、http等配置塊之前出現(xiàn),否則Nginx會報錯,提示“l(fā)oad_moduledirectiveisspecifiedtoolate”。目前Nginx硬性規(guī)定最多只能加載128個動態(tài)模塊。1.3.4運行日志配置日志是Web服務(wù)器非常重要的數(shù)字資產(chǎn),它記錄了服務(wù)器運行期間的各種信息,可以用來排查故障或者數(shù)據(jù)分析。在Nginx里運行日志分為兩種:記錄TCP/HTTP訪問請求的access_log和記錄服務(wù)器錯誤信息的error_log。本文只使用error_log,它可以在任意域里配置。指定Nginx的運行錯誤日志,默認(rèn)是安裝目錄下的logs/error.log。我們也可以自由設(shè)置其他路徑,或者使用標(biāo)準(zhǔn)錯誤輸出stderr。第二個參數(shù)level是日志的允許輸出級別,取值是debug|info|notice|warn|error|crit|alert|emerg,只有高于這個級別的日志才會記錄下來,默認(rèn)值是error。如果配置為最低的debug日志級別,那么在configure時必須使用“-with-debug”。1.3.5events配置Nginx采用事件驅(qū)動,利用操作系統(tǒng)內(nèi)核提供的epoll、kqueue等系統(tǒng)調(diào)用來高效地處理網(wǎng)絡(luò)連接,events配置塊就是用來配置Nginx的事件機(jī)制。雖然events配置很重要,但配置指令卻并不多,而且默認(rèn)設(shè)置就可以工作得很好。配置Nginx使用的事件處理方式,在Linux下可以選擇select、poll和epoll,其中epoll是最高效的,這也是Nginx的默認(rèn)設(shè)置,所以通常無需特意使用use指令。是否啟用進(jìn)程間的負(fù)載均衡機(jī)制。早期這個指令的默認(rèn)值是on,雖然可以讓多個worker進(jìn)程的工作量更均勻,但因為鎖的成本較高,很影響效率,所以1.11.3版之后Nginx把默認(rèn)值改成了off,也就是不啟用負(fù)載均衡機(jī)制。{L-End}與use指令一樣,不建議在配置文件里顯式寫出這個指令,而且最好把它關(guān)閉(off)。設(shè)置每個worker進(jìn)程可以處理的最大連接數(shù)量,它決定了Nginx的并發(fā)能力。注意此指令只是單個進(jìn)程的處理能力,Nginx的整體的最大可處理連接數(shù)應(yīng)該再乘上worker_processes的數(shù)量。例如,如果Nginx有10個worker,每個worker的連接數(shù)是1萬,那么Nginx理論上最多可以支持10*1萬=10萬個并發(fā)連接。1.3.6http配置Nginx近80%的功能都是提供HTTP服務(wù),所以HTTP的配置也是最復(fù)雜的。從1.3.1節(jié)可以看到,http配置塊幾乎占據(jù)了整個配置文件,而實際運行環(huán)境里的配置還會更加龐大。Nginx使用http塊配置HTTP相關(guān)的所有功能,包括cache、fastcgi、gzip、server、location、proxy、upstream等,通常的形式是:由于http塊內(nèi)容太多,如果都在一個文件里配置會造成配置文件過度龐大,難以維護(hù)。在實踐中我們通常把server、location等配置分離到單獨的文件,再利用include指令包含進(jìn)來,這樣就可以很好地降低配置文件的復(fù)雜度。使用include后http塊就簡化成了:在http塊里常用的有下面三個指令,配置HTTP服務(wù)的通用功能。這是個比較重要的指令,配置域名解析服務(wù)器,否則Nginx將無法正確解析域名的IP地址,也就無法訪問后端的Web服務(wù)。①keepalive_timeout指令也可以出現(xiàn)在server和location作用域里。設(shè)置keepalive的超時時間,默認(rèn)是75s。它通常有利于客戶端復(fù)用HTTP長連接,提高服務(wù)器的性能。如果希望服務(wù)器發(fā)送完數(shù)據(jù)后能夠主動斷連,就可以把它設(shè)置為0。access_logpath[format[buffer=size][flush=time][if=condition]];access_log指令用于配置http的訪問日志,日志的格式由log_format決定。為了優(yōu)化磁盤讀寫,可以設(shè)置buffer和flush選項,指定寫磁盤的緩沖區(qū)大小和刷新時間。下面的配置使用了8KB的緩存,每1秒刷新一次:1.3.7serve

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論