x86類型的CPU把指令分紅了四類:環0-環3,最內層爲核心指令即內核指令,其餘指令在環3上,歷史緣由環1,2沒有使用。html
分類:阻塞型、非阻塞型、複用型、信號驅動型、異步。nginx
同步/異步:web
關注消息通知機制:正則表達式
消息通知:
同步:等待對方返回消息;算法
異步:被調用者經過狀態、通知或回調機制通知調用者有關被調用者的運行狀態。express
阻塞/非阻塞:vim
關注調用者在等待結果返回以前所處的狀態:瀏覽器
阻塞:blocking,調用結果返回以前,調用者被掛起;緩存
非阻塞:nonblocking,調用結果返回以前,調用者不被掛起。性能優化
一次文件I/O請求,都會由兩階段組成:
第一步:等待數據,即數據從磁盤到內核內存;
第二步:複製數據,即數據從內核內存到進程內存。
已上的I/O分類就是給予上述兩步來劃分的:
阻塞型:已上兩步均被阻塞;
非阻塞型:第一步是非阻塞的,第二步是阻塞的;
複用型:一個進程能監視多路I/O,此時須要一個特殊的內核函數(I/O複用器)去監視iI/O;
信號驅動型:屬於異步I/O,第一步再也不阻塞,調用後再也不等待結果,繼續執行其餘任務;
異步:屬於異步I/O,不管第一步和第二步均不參與,由內核去完成。
複用型I/O調用:
Linux:
select:1024(一個進程最多監視1024個I/O,屢次測試的結果,是由BSD發明)
poll():沒有限制,是由UNIX
信號驅動型(event-driven):
epoll(Linux):由 libevent包來實現
Kqueue(BSD):
/dev/poll(Solaris)
多處理模塊(MPM),用來綁定到網絡端口上,接受請求, 以及調度子進程處理請求。在更高伸縮性的站點能夠選擇使用線程的 MPM,即 worker
或 event
; 須要可靠性或者與舊軟件兼容的站點可使用 prefork
。
prefork模型:進程模型,二級結構,主進程master負責生成子進程,每一個子進程負責響應一個請求;
worker模型:線程模型,三級結構,主進程master負責生成子進程,每一個子進程負責生成多個線程,每一個線程響應一個請求;
event模型:二級結構,主進程master負責生成子進程,每一個子進程響應多個請求(相似線程模型)。
nginx有三種功能:web服務(靜態的web資源服務器),web反向代理,郵件反向代理
一個master進程:
負責加載和分配配置文件、管理worker進程、平滑升級
一個或者多個worker進程:
處理並響應用戶請求
緩存相關的進程:
cache loader: 載入緩存對象
cache manager: 管理緩存對象
特性:異步,事件驅動和非阻塞
併發請求處理:經過kevent/epoll/select,/dev/poll實現,此處須要注意epoll和select,優先使用epoll;
文件I/O: 高級I/O、sendfile、異步、mmap
Nginx高度模塊化機制,但其模塊早期不支持DSO機制,近期支持模塊動態裝載和卸載。
模塊分類:核心模塊和標準模塊、第三方模塊。
3.2.1 核心模塊(core module)
3.2.2 標準模塊
HTTP modules:
standard HTTP modules:
Optional HTTP modules(可選的http模塊) :
Mail modules
Stream modules(流模塊):實現傳輸層代理(屬於四層代理)
3.2.2 第三方模塊
配置指令:
4.1 性能優化相關的配置
worker_processes number | auto
一般對應cpu核心數;
worker_cpu_affinity auto | cpumask
將進程綁定在cpu上;
worker_priority number | cpumask
指定worker進程的nice值,設定worker進程的優先級[-20,20];
worker_rlimit_nofile_number
worker進程所可以打開的文件數量上限;
sendfile系統調用在兩個文件描述符之間直接傳遞數據(徹底在內核中操做),從而避免了數據在內核緩衝區和用戶緩衝區之間的拷貝,操做效率很高,被稱之爲零拷貝。可是隻適用於靜態資源服務器,對於反向代理則無用。
原理解釋 read/write 在傳統的文件傳輸方式(read、write/send方式),具體流程細節以下: 調用read函數,文件數據拷貝到內核緩衝區 read函數返回,數據從內核緩衝區拷貝到用戶緩衝區 調用write/send函數,將數據從用戶緩衝區拷貝到內核socket緩衝區 數據從內核socket緩衝區拷貝到協議引擎中 在這個過程中,文件數據其實是通過了四次拷貝操做: 硬盤—>內核緩衝區—>用戶緩衝區—>內核socket緩衝區—>協議引擎 sendfile sendfile系統調用則提供了一種減小拷貝次數,提高文件傳輸性能的方法。 sendfile系統調用利用DMA引擎將文件數據拷貝到內核緩衝區,以後數據被拷貝到內核socket緩衝區中 DMA引擎將數據從內核socket緩衝區拷貝到協議引擎中 這裏沒有用戶態和內核態之間的切換,也沒有內核緩衝區和用戶緩衝區之間的拷貝,大大提高了傳輸性能。 這個過程數據經歷的拷貝操做以下: 硬盤—>內核緩衝區—>內核socket緩衝區—>協議引擎 帶有DMA收集拷貝功能的sendfile 對於帶有DMA收集拷貝功能的sendfile系統調用,還能夠再減小一次內核緩衝區之間的拷貝。具體流程以下: sendfile系統調用利用DMA引擎將文件數據拷貝到內核緩衝區,以後,將帶有文件位置和長度信息的緩衝區描述符添加到內核socket緩衝區中 DMA引擎會將數據直接從內核緩衝區拷貝到協議引擎中 這個過程數據經歷的拷貝操做以下: 硬盤—>內核緩衝區—>協議引擎
4.2 定義客戶端請求的相關配置
keepalive_timeout
keepalive_timeout timeout [header_timeout];
設定保持鏈接超時時長,0表示禁止長鏈接,默認爲75s,能夠調整短點。
keepalive_requests
keepalive_requests number;
在一次長鏈接上所容許請求的資源的最大數量,默認爲100
keepalive_disable
keepalive_disable none | browser ...
對哪一種瀏覽器禁用長鏈接
send_timeout
send_timeout time;
向客戶端發送響應報文的超時時長,此處是指兩次寫操做之間的間隔時長,而非整個響應過程的傳輸時長
client_body_buffer_size
client_body_buffer_size size;
用於接收每一個客戶端請求報文的body部分的緩衝區大小;默認爲16k;超出此大小時,其將被暫存到磁盤上的由client_body_temp_path指令所定義的位置。注意,這裏是接收,不是下發數據,上傳文件到該網站,纔看獲得效果
client_body_temp_path
client_body_temp_path path [level1 [level2 [level3]]];
設定用於存儲客戶端請求報文的body部分的臨時存儲路徑及子目錄結構和數量
這裏指定的路徑下存放文件,目錄名爲16進制的數字,是通過hash運算後,利用hash的值的最後幾位數,依次分層,如三層目錄進行存放文件
例子
client_body_temp_path /var/tmp/client_body 1 2 2
1 1級目錄佔1位16進制,即2^4=16個目錄0-f
2 2級目錄佔2位16進制,即2^8=256個目錄00-ff
2 3級目錄佔2位16進制,即2^8=256個目錄00-ff
4.3 對客戶端進行限制的相關配置
.1九、limit_rate
limit_rate rate;
限制響應給客戶端的傳輸速率,單位是bytes/second,默認值0表示無限制
.20、limit_except
limit_except method ... { ... },僅用於location
限制客戶端使用除了指定的請求方法以外的其它方法
method:GET, HEAD, POST, PUT, DELETE,MKCOL, COPY, MOVE,OPTIONS, PROPFIND,PROPPATCH, LOCK, UNLOCK, PATCH
location { limit_except GET { allow 192.168.1.0/24; deny all; } }
除了GET和HEAD 以外其它方法僅容許192.168.1.0/24網段主機使用
4.4 文件操做優化的配置
aio
對於大文件採用aio,節省cpu,而對於小文件,採用sendfile,減小拷貝;而且對於大文件aio採用directio,避免擠佔文件系統緩存,讓文件系統緩存更多的小文件。
aio on | off | threads[=pool];是否啓用aio功能,默認是on
directio
directio size | off;通常是異步
是否同步(直接)寫磁盤,而非寫緩存,在Linux主機啓用O_DIRECT標記,則文件大於等於給定大小時使用,例如directio 4m
open_file_cache
open_file_cache off;
open_file_cache max=N [inactive=time];
nginx能夠緩存如下三種信息:緩存的是元數據,不是數據自己
(1) 文件元數據:文件的描述符、文件大小和最近一次的修改時間
(2) 打開的目錄結構
(3) 沒有找到的或者沒有權限訪問的文件的相關信息
max=N:可緩存的緩存項上限;達到上限後會使用LRU算法實現管理
inactive=time:緩存項的非活動時長,在此處指定的時長內未被命中的或命中的次數少於open_file_cache_min_uses指令所指定的次數的緩存項即爲非活動項,將被刪除
inactive=time 爲10分鐘;open_file_cache_min_uses爲3,表示在10分鐘內訪問低於3次表示非活動的,該文件就不會被緩存,會被清空
open_file_cache_errors
open_file_cache_errors on | off;
是否緩存查找時發生錯誤的文件一類的信息,默認值爲off
open_file_cache_min_uses
open_file_cache_min_uses number;
open_file_cache指令的inactive參數指定的時長內,至少被命中此處指定的次數方可被歸類爲活動項,默認值爲1
open_file_cache_valid
open_file_cache_valid time;
緩存項有效性的檢查頻率,默認值爲60s
4.5 Nginx 之 實現https
要利用nginx軟件實現https的頁面,用到ngx_http_ssl_module模塊
一、ssl
ssl on | off;
爲指定虛擬機啓用HTTPS protocol,建議用listen指令代替
二、ssl_certificate
ssl_certificate file;
當前虛擬主機使用PEM格式的證書文件
建立自簽名的證書文件
cd /etc/pki/tls/certs/
make nginx6.crt
將生成的私鑰文件解密
將這兩個文件複製到配置文件裏指定的路徑便可
在客戶的上查看生成的證書信息,命令以下
openssl s_client -connect www.e.com:443
三、ssl_certificate_key
ssl_certificate_key file;
當前虛擬主機上與其證書匹配的私鑰文件
四、ssl_protocols
ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];
支持ssl協議版本,默認爲後三個,主流版本是[TLSv1.2]
五、ssl_session_cache
ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
builtin[:size]:使用OpenSSL內建緩存,爲每worker進程私有,開啓多大的空間來做爲緩存空間
[shared:name:size]:在各worker之間使用一個共享的緩存,這樣會提升緩存的命中率,提升性能。
六、ssl_session_timeout
ssl_session_timeout time;
客戶端鏈接能夠複用sslsession cache中緩存的ssl參數的有效時長,默認5m
示例:
vim /etc/nginx/conf.d/https.conf server{ listen 443 ssl; server_name www.e.com; root /app/website5; ssl_certificate /etc/nginx/ssl/nginx5.crt; ssl_certificate_key/etc/nginx/ssl/nginx5.key; ssl_session_cache shared:sslcache:20m; ssl_session_timeout 10m; } server{ listen 443 ssl; server_name www.f.com; root /app/website6; ssl_certificate /etc/nginx/ssl/nginx6.crt; ssl_certificate_key/etc/nginx/ssl/nginx6.key; ssl_session_cache shared:sslcache:20m; ssl_session_timeout 10m; }
4.6 ngx_http_rewrite_module模塊:
將用戶請求的URI基於PCRE regex所描述的模式進行檢查,然後完成重定向替換
當舊的業務和新的業務不同,網站改名了,如網站名原來是www.dianping.com/zz後面更名爲www.dianping.com/zhengzhou
一、rewrite
rewrite regex replacement [flag]
將用戶請求的URI基於regex所描述的模式進行檢查,匹配到時將其替換爲replacement指定的新的URI
注意:若是在同一級配置塊中存在多個rewrite規則,那麼會自上而下逐個檢查;被某條件規則替換完成後,會從新一輪的替換檢查
隱含有循環機制,但不超過10次;若是超過,提示500響應碼,[flag]所表示的標誌位用於控制此循環機制
若是replacement是以http://或https://開頭,則替換結果會直接以重向返回給客戶端
.[flag]:有如下幾個關鍵字
last:重寫完成後中止對當前URI在當前location中後續的其它重寫操做,然後對新的URI啓動新一輪重寫檢查;提早重啓新一輪循環
break:重寫完成後中止對當前URI在當前location中後續的其它重寫操做,然後直接跳轉至重寫規則配置塊以後的其它配置;結束循環,建議在location中使用
last 和break是在服務器內部操做的,客戶端不知道,客戶端訪問的url不會發生變化。可是服務器端會返回替換過的新的內容。
redirect和permanent是服務器端給客戶端發一個301或者302的請求,客戶端須要從新發起請求,所以最終客戶端看到的瀏覽器是url和原始的url是不同的,url會被轉換,如將fj改爲成fujian,那麼當用戶訪問的是http://172.18.50.73/fj/ 最終返回結果的時候,瀏覽器上的url會變動改成http://172.18.50.73/fujian/
redirect:臨時重定向,重寫完成後以臨時重定向方式直接返回重寫後生成的新URI給客戶端,由客戶端從新發起請求;不能以http://或https://開頭,使用相對路徑,狀態碼:302
permanent:重寫完成後以永久重定向方式直接返回重寫後生成的新URI給客戶端,由客戶端從新發起請求,狀態碼:301
例子
如下是正則表達式,$1表示前面的(.*).寫在server段或者location段裏,如下四個選項只需四選一。
測試
curl -L http://172.18.50.73/fj/
或者直接在瀏覽器裏輸入http://172.18.50.73/fj/查看結果
二、return
return 返回一個具體的地址
return code [text];
return code URL;
中止處理並將指定的代碼返回給客戶端。非標準代碼444關閉鏈接而不發送響應頭。
從版本0.8.42開始,能夠指定重定向URL(代碼301,302,303,307和308)或響應正文文本(對於其餘代碼)。響應正文文本和重定向網址能夠包含變量。做爲特殊狀況,重定向URL能夠指定爲此服務器本地的URI,在這種狀況下,根據請求方案($ scheme)和server_name_in_redirect和port_in_redirect指令造成完整的重定向URL。
此外,能夠將用於代碼302的臨時重定向的URL指定爲惟一的參數。這樣的參數應以「http://」,「https://」或「$ scheme」字符串開頭。 URL能夠包含變量。
測試,能正常返回text,
return URL;
中止處理,並返回給客戶端指定的響應碼。可是實際測試都是屢次循環重定向,致使url不能打開,用curl命令測試,出現了報錯:curl: (47) Maximum(50) redirects followed致使實驗不成功
三、rewrite_log
rewrite_log on | off;
是否開啓重寫日誌, 發送至error_log(notice level)
四、set
set $variable value;
用戶自定義變量,注意:變量定義和調用都要以$開頭
五、if
if (condition) { ... }
引入新的上下文,條件知足時,執行配置塊中的配置指令;server,location
condition:比較操做符:
== 相同
!= 不一樣
~:模式匹配,區分字符大小寫
~*:模式匹配,不區分字符大小寫
!~:模式不匹配,區分字符大小寫
!~*:模式不匹配,不區分字符大小寫
文件及目錄存在性判斷:
-e, !-e 存在(包括文件,目錄,軟連接)
-f, !-f 文件
-d, !-d 目錄
-x, !-x 執行
4.7 ngx_http_referer_module模塊
referer是指從哪兒跳轉,該字段能夠用來防止盜鏈。
好比網頁內有代碼<a href=http://172.18.50.73/m.txt>test referer </a>那麼再網頁上test referer就會有連接到資源http://172.18.50.73/m.txt上,點擊該連接,log就會有對應的referer在code以後,如這裏是http://172.18.50.73/a.html,若是沒有referer,則code後的字段顯示「-」
.一、valid_referers none|blocked|server_names|string...;
定義referer首部的合法可用值,不能匹配的將是非法值
none:請求報文首部沒有referer首部
blocked:請求報文有referer首部,但無有效值
server_names:參數,其能夠有值做爲主機名或主機名模式
arbitrary_string:任意字符串,但可以使用*做通配符
regular expression:被指定的正則表達式模式匹配到的字符串,要使用~開頭,例如:~.*\.magedu\.com
.示例:
#定義有效的referers
#定義若是出現無效的referer將返回code 403