深入理解Nginx 模块开发与架构解析-陶辉 读书笔记
前言
1. nginx是一個優秀的事件驅動框架,nginx非常適合開發在傳輸層以TCP對外提供服務的服務器程序。基于nginx框架開發程序有5個優勢:
* nginx將網絡、磁盤及定時器等異步事件的驅動都做了非常好的封裝,基于它開發將可以忽略這些事情處理的細節
* nginx封裝了許多平臺無關的接口、容器,適用于跨平臺開發
* 優秀的模塊化設計,使得開發者可以輕易的復用各種已有的模塊,其中既包括基本的讀取配置、記錄日志等模塊,也包括處理請求的諸如http、mail等高級功能模塊
* nginx是作為服務器來設計其框架的,因此,它在服務器進程的管理上相當出色,基于它開發服務器程序可以輕松地實現程序的動態升級,子進程的監控、管理,配置項的動態修改生效等。
* nginx充分考慮到各操作系統所擅長的“絕活”,能夠使用特殊的系統調用更高效地完成任務時,絕不會去使用低效的通用接口。尤其對于Linux操作系統,nginx不遺余力地做了大量優化。
第一部分
nginx能幫我們做什么
第一章?
研究nginx前的準備工作
1. 2012年,nginx榮獲年度云計算開發獎,并成為世界第二大web服務器
1.1 nginx是什么?
1. web服務器的基本功能:基于REST架構風格,以統一資源描述符(uniform resource identifier, URI)或統一資源定位符(uniform resource locator, URL)作為溝通依據,通過http為瀏覽器等客戶端程序提供各種網絡服務。
2. nginx的競爭對手---Apache,Lighttpd, tomcat,jetty, IIS。他們都是web服務器,或者叫做WWW服務器。、
3. nginx是一個跨平臺的web服務器,可運行在Linux,FreeBSD,Solaris,AIX,MacOS,Windows等操作系統上,并且它還可以使用當前操作系統特有的一些高效API來提高自己的性能
1.2 為什么選擇nginx
1. nginx具備以下特點
* 更快
* 高擴展性
* 高可靠性
* 低內存消耗
* 單機支持10萬以上的并發連接
* 熱部署
* 最自由的BSD許可協議
nginx的核心優點還是他能夠在支持高并發請求的同時保持高效的服務
1.3.1 Linux操作系統
1. 系統必須是內核為Linux 2.6 及以上版本的操作系統,因為Linux 2.6及以上內核才支持epoll,而在Linux上使用select或poll來解決事件的多路復用,是無法解決高并發壓力問題的。
2. uname -a 查詢Linux內核版本
1.3.3 磁盤目錄
1. nginx編譯階段產生的中間文件存放目錄
該目錄用于放置configure命令執行后所產生的源文件及目錄,以及make命令執行后生成的目標文件和最終連接成功的二進制文件。默認情況下,configure命令會將該目錄命名為objs
第十四章
進程間的通信機制
1. ?nginx由一個master進程和多個worker進程組成,但master進程或者worker進程中并不會再創建線程(nginx的多線程機制一直停留在測試狀態,雖然不排除未來nginx可能發布支持多線程版本的可能性)
14.1
1. nginx框架使用了3種傳遞消息傳遞方式:共享內存、套接字、信號
2. nginx主要使用了3種同步方式:原子操作、信號量、文件鎖
14.2 共享內存
1. 共享內存是Linux下提供的最基本的進程間通信方法,它通過mmap或者shmget系統調用在內存中創建了一塊連續的線性地址空間,而通過munmap或者shmdt系統調用可以釋放這塊內存
使用共享內存的好處是當多個進程使用同一塊共享內存時,在任何一個進程修改了共享內存中的內容后,其他進程通過訪問這段共享內存都能夠得到修改后的內容
2. nginx各進程間共享數據的主要方式就是使用共享內存,在使用共享內存時,nginx一般是由master進程創建,在master進程fork出worker子進程后,所有的進程開始使用這塊內存中的數據
14.3 原子操作
1. 能夠執行原子操作的原子變量只有整型,包括無符號整型ngx_atomic_uint_t和有符號整型ngx_atomic_t。這兩種類型都使用了volatile關鍵字告訴C編譯器不要做優化。
14.3.1 不支持原子庫下的原子操作
14.3.3 自旋鎖
1. 基于原子操作,nginx實現了一個自旋鎖。
2. 自旋鎖是一種非睡眠鎖,也就是說,某進程如果試圖獲得自旋鎖,當發現鎖已經被其他進程獲得時,那么不會使得當前進程進入睡眠狀態,而是始終保持進程在可執行狀態,每當內核調度到這個進程執行時就持續檢查是否可以獲取到鎖。在拿不到鎖時,這個進程的代碼將會一直在自旋鎖代碼處執行,直到其他進程釋放了鎖且當前進程獲取了鎖后,代碼才會繼續向下執行。
3. 自旋鎖主要是為多處理器操作系統而設置的,它要解決的共享資源保護場景就是進程使用鎖的時間非常短,如果鎖的使用時間很久,自旋鎖會不太合適,那么它會占用大量的CPU資源
4. ngx_spinlock方法是非常高效的自旋鎖,它充分考慮了單處理器和多處理器的系統,對于持有鎖時間非常短的場景很有效率
14.4 nginx頻道
1. ngx_channel_t頻道是nginx master進程與worker進程之間通信的常用工具,它是使用本機套接字實現的。
int socketpair( int d, int type, int portocol, int sv[2]); 創建父子進程間使用的套接字
2. 當socketpair執行成功時,sv[2]這兩個套接字具備下列關系:向sv[0]套接字寫入數據,將可以從sv[1]套接字中讀取到剛寫入的數據;同樣,向sv[1]套接字寫入數據,也可以從sv[0]中讀取到寫入的數據。
通常,在父子進程通信前,會先調用socketpair方法創建這樣一組套接字,在調用fork方法創建出子進程后,將會在父進程中關閉sv[1]套接字,僅使用sv[0]套接字用于向子進程發送數據以及接受子進程發送來的數據;而在子進程中則關閉sv[0]套接字,僅使用sv[1]套接字既可以接受父進程發來的數據,也可以向父進程發送數據
3. master進程如何監控、管理worker子進程?
每次派生一個子進程之前,也就是fork之前,都會先調用socketpair方法,在nginx派生子進程ngx_spawn_process方法中,會首先派生基于TCP的套接字,master正是通過socketpair產生的套接字發送命令的。
14.5 信號
1. Linux提供了以信號傳遞進程間消息的機制,nginx在管理master進程和worker進程時大量使用了信號。
2. 信號和信號量是完全不同的概念,信號量僅用于同步代碼段,而信號則用于傳遞消息。一個進程可以向另外一個進程或者另外一組進程發送信號消息,通知目標進程執行特定的代碼
./nginx -s reload
14.6 信號量
1. 信號量是用來保證兩個或多個代碼段不被并發訪問,是一種保證共享資源有序訪問的工具,使用信號量作為互斥鎖有可能導致進程睡眠,因此,要謹慎使用。
2. int sem_init( sem_t* sem, int pshared, unsigned int value);
初始化信號量,?pshared為0時表示線程間同步,為1時表示進程間同步。
3.?int sem_destroy(sem_t *sem)
銷毀信號量
4.?int sem_post(sem_t *sem);
信號量的值加一
5.?int sem_wait(sem_t * sem);
信號量的值減一
14.7 文件鎖
1. Linux內核提供了基于文件的互斥鎖
int fcntl(int fd, int cmd, struct flock* lock);
fd 是打開的文件句柄,cmd 表示執行的鎖操作,lock描述了這個鎖的信息。
2. nginx.conf文件中的lock_file配置項指定的文件路徑,就是用于文件互斥鎖的。
3. 對于文件鎖,nginx封裝了3個方法:ngx_trylock_fd實現了非阻塞進程,不會使進程進入睡眠狀態的互斥鎖
ngx_lock_fd 阻塞互斥鎖
ngx_unlock_fd 釋放互斥鎖
14.8 互斥鎖
總結:nginx是一個能夠并發處理幾十萬甚至幾百萬個TCP連接的高性能服務器,因此,在進行進程間通信時,必須充分考慮到不能過分影響正常請求的處理
p20
總結
以上是生活随笔為你收集整理的深入理解Nginx 模块开发与架构解析-陶辉 读书笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 运行中的Nginx进程间的关系
- 下一篇: Linux网络编程 -- socketp