瞭解Nginx
1。 安裝Nginx
版本 nginx-1。14。0
如果想學習Java工程化、高效能及分散式、深入淺出。微服務、Spring,MyBatis,Netty原始碼分析的朋友可以加我的Java高階交流:854630135,群裡有阿里大牛直播講解技術,以及Java大型網際網路技術的影片免費分享給大家。
# 安裝C++編譯器 yum -y install gcc-c++ # 下載並安裝OpenSSL openssl-fips-2。0。16。tar。gz tar -zxf openssl-fips-2。0。16。tar。gz cd openssl-fips-2。0。16 。/config && make && make install # 下載並安裝pcre pcre-8。42。tar。g tar -zxf pcre-8。42。tar。g cd pcre-8。42 。/configure && make && make install # 下載並安裝zlib zlib-1。2。11。tar。gz tar -zxf zlib-1。2。11。tar。gz cd zlib-1。2。11 。/configure && make && make install # 下載並安裝Nginx nginx-1。14。0。tar。gz tar -zxf nginx-1。14。0。tar。gz cd nginx-1。14。0 。/configure && make && make install
2。 快速開始
nginx有一個master程序和多個worker程序。
master程序主要負責讀取和評估配置,並維護worker程序。
worker程序負責實際的請求處理。worker程序的數量在配置檔案中定義,可以指定一個固定值,也可以根據可用CPU核心的數量自動調整。
nginx及其模組的工作方式由配置檔案決定。預設情況下,配置檔案的名字叫nginx。conf,並且所在位置是/usr/local/nginx/conf, /etc/nginx, 或 /usr/local/etc/nginx
2。1。 啟動/停止/重新載入配置
為了啟動nginx,執行可執行檔案nginx。一旦nginx啟動以後,就可以透過 -s 引數來控制它。
用下面的語法格式:
如果想學習Java工程化、高效能及分散式、深入淺出。微服務、Spring,MyBatis,Netty原始碼分析的朋友可以加我的Java高階交流:854630135,群裡有阿里大牛直播講解技術,以及Java大型網際網路技術的影片免費分享給大家。
例如,為了停止nginx程序,並且等待worker程序完成當前請求的處理,可以執行下面的命令:
nginx -s quit
(畫外音:執行這個命令的使用者必須與啟動nginx的使用者相同)
為了重新載入配置,執行下面的命令:
nginx -s reload
一旦master程序收到重新載入配置的訊號以後,它檢查配置檔案的語法,並嘗試應用配置檔案中提供的配置。如果成功的話,master程序會啟動一個新的worker程序並且傳送訊息給舊的worker程序請求它們立即shut down。否則,master程序回滾本次更改,繼續用舊的配置工作。當舊的worker程序收到一個shut down的命令時,它停止接受新的連線,並繼續服務當前請求,直到它收到的所有請求都處理完成。此後,舊的worker程序就退出了。
在Unix工具的幫助下(比如 kill)也可以向nginx程序傳送訊號。在這種情況下,訊號直接被髮送到給定的程序ID所代表的程序。預設情況下,nginx master程序的程序ID被寫入nginx。pid檔案中,該檔案所在目錄通常是/usr/local/nginx/logs 或 /var/run。例如,如果master程序ID是1628,那麼為了傳送QUIT訊號給nginx,執行下面的命令:
kill -s QUIT 1628
為了獲取所有正在執行的nginx程序列表,可以使用ps命令,例如:
ps -ax | grep nginx
2。2。 配置檔案的結構
nginx由配置檔案中的指令所控制的模組組成。指令分為簡單指令和塊指令。簡單指令由名稱和引數組成,它們之間用空格隔開,以分號(;)結束。塊指令的結構與簡單指令相同,但它不是以分號結尾,而是一組由大括號({ 和 })包圍的附加指令。如果一個block指令可以在大括號中包含其他指令,那麼它被成為上下文(例如:events, http, server 和 location)。events 和 http 指令在main上下文下,server指令在http中,location在server中。
預設的配置檔案nginx。conf如下:
#
user nobody; worker_processes 1;
#
error_log logs/error。log;
#
error_log logs/error。log notice;
#
error_log logs/error。log info;
#
pid logs/nginx。pid; events { worker_connections 1024; } http { include mime。types; default_type application/octet-stream;
#
log_format main ‘$remote_addr - $remote_user [$time_local] “$request” ’
#
‘$status $body_bytes_sent “$http_referer” ’
#
‘“$http_user_agent” “$http_x_forwarded_for”’;
#
access_log logs/access。log main; sendfile on;
#
tcp_nopush on;
#
keepalive_timeout 0; keepalive_timeout 65;
#
gzip on; server { listen 80; server_name localhost;
#
charset koi8-r;
#
access_log logs/host。access。log main; location / { root html; index index。html index。htm; }
#
error_page 404 /404。html;
#
redirect server error pages to the static page /50x。html
#
error_page 500 502 503 504 /50x。html; location = /50x。html { root html; }
#
proxy the PHP scripts to Apache listening on 127。0。0。1:80
#
#
location ~ \。php$ {
#
proxy_pass http://127。0。0。1;
#
}
#
pass the PHP scripts to FastCGI server listening on 127。0。0。1:9000
#
#
location ~ \。php$ {
#
root html;
#
fastcgi_pass 127。0。0。1:9000;
#
fastcgi_index index。php;
#
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
#
include fastcgi_params;
#
}
#
deny access to 。htaccess files, if Apache‘s document root
#
concurs with nginx’s one
#
#
location ~ /\。ht {
#
deny all;
#
} }
#
another virtual host using mix of IP-, name-, and port-based configuration
#
#
server {
#
listen 8000;
#
listen somename:8080;
#
server_name somename alias another。alias;
#
location / {
#
root html;
#
index index。html index。htm;
#
}
#
}
#
HTTPS server
#
#
server {
#
listen 443 ssl;
#
server_name localhost;
#
ssl_certificate cert。pem;
#
ssl_certificate_key cert。key;
#
ssl_session_cache shared:SSL:1m;
#
ssl_session_timeout 5m;
#
ssl_ciphers HIGH:!aNULL:!MD5;
#
ssl_prefer_server_ciphers on;
#
location / {
#
root html;
#
index index。html index。htm;
#
}
#
} }
如果想學習Java工程化、高效能及分散式、深入淺出。微服務、Spring,MyBatis,Netty原始碼分析的朋友可以加我的Java高階交流:854630135,群裡有阿里大牛直播講解技術,以及Java大型網際網路技術的影片免費分享給大家。
2。3。 服務靜態內容
Web伺服器其中一個重要的任務是提供檔案(比如,圖片和靜態HTML頁面)。
首先,讓我們來建立/data/html目錄,並在其中放一個index。html檔案。同時再建一個/data/images目錄用於放置圖片。
接下來,開啟配置檔案,在預設的配置檔案中server塊下已經包含了一些例子,通常它們是被註釋了的。
以/images/開頭的請求,伺服器將從/data/images目錄下查詢並返回檔案。
例如:
http://
192。168。101。5/images/a。
png
請求,伺服器將返回/data/images/a。png檔案,如果這個檔案不存在,則返回404。
不是以/images/開頭的的請求將對映到/data/html目錄。
http://
192。168。101。5/
http://
192。168。101。5/index。htm
l
http://
192。168。101。5/example。h
tml
root指令:
2。4。 簡單的代理伺服器
首先,透過在配置檔案中提那家一個或多個server塊來定義代理伺服器
上面的例子中定義了一個簡單伺服器,它監聽8080埠,並且把所有請求對映到本地/data/up1目錄。注意,這裡root指令放在了server上下文。當一個請求不包含location它在自己的root指令中,則會使用這個server上下文中的root指令。(畫外音:簡單的來說,location指令中的root相當於區域性變數,而server指令下的root相當於全域性變數,當請求不匹配區域性變數時,則使用全域性變數。類比Java就是一個是自定義的方法,一個是預設實現的方法)
接下來,修改前面的配置。我們在第一個location塊中放置proxy_pass指令
http://
nginx。org/en/docs/http/
ngx_http_proxy_module。html
引數是一個匹配所有以。gif, 。jpg, 或者。png結尾的URIs的正則表示式。與之相應的,請求被對映到/ata/images目錄。
location指令的引數是正則表示式
在正則表示式前面應該加上~
當nginx選擇一個location塊來服務一個請求時,它首先檢查location指令所指定的字首,記住最長的字首的那個location,然後檢查正則表示式。如果匹配正則表示式,則挑選這個location,否則挑選他所記住的更早的那個。
(畫外音:這段話解釋了nginx是如何挑選location的,我們可以這樣理解,透過location指令所指定的字首,從最長的字首開始匹配,如果滿足,則挑選這個,否則,檢查第二長的,依次嘗試匹配,直到找到一個匹配的location)
如果想學習Java工程化、高效能及分散式、深入淺出。微服務、Spring,MyBatis,Netty原始碼分析的朋友可以加我的Java高階交流:854630135,群裡有阿里大牛直播講解技術,以及Java大型網際網路技術的影片免費分享給大家。
3。 常用指令
http://
nginx。org/en/docs/http/
ngx_http_core_module。html
3。1。 location
一個location定義可以是一個字首字串,也可以是一個正則表示式。正則表示式使用的時候要在前面用“~*”修飾符(用於不區分大小寫匹配),或者“~”修飾符(用於區分大小寫)。為了找到請求匹配的location,nginx首先檢查location定義,用字首字串(這些location成為字首location)。其中,最長匹配字首的location會被選中並記住。然後,檢查正則表示式,按照它們在配置檔案中出現的順序。對正則表示式的搜尋在第一次匹配時終止,並使用相應的配置。如果沒有找到與正則表示式的匹配,則使用前面記住的字首位置的配置。
(
畫外音:首先檢查字首字串,然後檢查正則表示式
1、用字首字串(字首location)匹配URL,並且選中並記住最長匹配字首的location(注意:是在匹配的裡面記住最長的那個)
2、按照正則表示式在配置檔案中出現的順序依次去匹配,當匹配到第一個以後立即停止,並使用與之相應的那個location。如果沒有一個正則表示式匹配,則使用之前記住的那個字首location。
以上,我們可以得出一個結論:優先使用正則表示式,如果沒有匹配的正則表示式發現,則使用匹配的最長字首字串location
)
例如:
5。 ngx_http_proxy_module模組
ngx_http_proxy_module模組允許將請求傳遞到另一個伺服器。例如:
5。1。 proxy_pass指令
設定代理伺服器的協議和地址,以及應該對映哪一個可選URI。作為協議,可以指定“http”或“https”。地址可以指定為一個域名或IP地址,以及一個可選埠:
如果想學習Java工程化、高效能及分散式、深入淺出。微服務、Spring,MyBatis,Netty原始碼分析的朋友可以加我的Java高階交流:854630135,群裡有阿里大牛直播講解技術,以及Java大型網際網路技術的影片免費分享給大家。
請求URI傳遞給伺服器:
如果proxy_pass指令帶一個特定的URI,那麼請求被傳給給這個伺服器,正常的請求URI部分被指令中指定的URI替換,例如:
如果proxy_pass指令不帶URI,那麼請求URI在傳遞給伺服器的時候和原始請求是一樣的,例如:
在有些情況下,請求URI部分不能決定該如何替換:
1、當location時用一個正則表示式指定的時候,或者用內部的location命中指定的時候。
那麼在這種情況下,proxy_pass在指定的時候不應該帶URI
2、當用rewrite指令更改location時
在這種情況下,在指令中指定的URI將被忽略
(
http://
nginx。org/en/docs/http/
ngx_http_rewrite_module。html
)
3、當在proxy_pass中使用變數時
在這種情況下,如果指令中指定了URI,那麼將被傳遞給伺服器,並替換原始請求URI
6。 ngx_http_limit_req_module模組(限流)
ngx_http_limit_req_module模組用於限制指定的key的請求處理速率,特別是來自單個IP地址的請求處理速率。這種限制使用的是“漏桶演算法”。
例如:
6。1。 limit_req指令
設定共享記憶體區域和請求的最大突發大小。如果請求速率超過了為區域配置的速率,那麼它們的處理就會延遲,這樣請求就會以指定的速率進行處理。過多的請求被延遲,直到它們的數量超過最大突發大小,在這種情況下,以一個錯誤來終止請求。預設情況下,突發數量等於0。
平均每秒不允許超過1個請求,突發不超過5個請求。
如果不希望在請求受到限制時延遲過多的請求,則應使用引數nodelay:
可以有多個limit_req指令。例如,以下配置將限制來自單個IP地址的請求的處理速率,同時限制虛擬伺服器的請求處理速率:
6。2。 limit_req_zone指令
設定共享記憶體區域引數。key可以包含文字、變數、以及它們的組合。
這個例子中,“one”這個區域維護的記憶體是10M,並且這個區域的平均請求處理速率不能超過每秒1個請求。
7。 控制Nginx
8。 用Nginx作為負載均衡器
8。1。 負載均衡方法
nginx支援以下負載平衡機制(或方法):
8。2。 預設的負載均衡配置
如果想學習Java工程化、高效能及分散式、深入淺出。微服務、Spring,MyBatis,Netty原始碼分析的朋友可以加我的Java高階交流:854630135,群裡有阿里大牛直播講解技術,以及Java大型網際網路技術的影片免費分享給大家。
在上面的例子彙總,同一個應用運行了3個例項。預設的負載均衡策略是迴圈。
8。3。 最少連線的負載均衡
另一個負載平衡原則是最少連線的。在某些請求需要更長的時間才能完成的情況下,最少連線允許更公平地控制應用程式例項上的負載。
使用連線最少的負載平衡,nginx將盡量不讓繁忙的應用伺服器超載過多的請求,而是將新請求分發到不那麼繁忙的伺服器。
例如:
8。4。 Session持久化
使用迴圈或最少連線負載平衡,每個後續客戶機的請求都可能被分發到不同的伺服器。不能保證同一個客戶端總是指向同一個伺服器。
使用IP-hash,客戶端的IP地址用作雜湊key,以確定應該為客戶端請求選擇伺服器組中的哪個伺服器。此方法確保來自同一客戶端的請求總是指向同一伺服器,除非該伺服器不可用。
例如:
如果想學習Java工程化、高效能及分散式、深入淺出。微服務、Spring,MyBatis,Netty原始碼分析的朋友可以加我的Java高階交流:854630135,群裡有阿里大牛直播講解技術,以及Java大型網際網路技術的影片免費分享給大家。
8。5。 帶權重的負載均衡
還可以透過使用伺服器權值進一步影響nginx的負載平衡演算法。
在上面的示例中,沒有配置伺服器權重,這意味著所有指定的伺服器都被視為具有同等資格的特定負載平衡方法。