瞭解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
瞭解Nginx

瞭解Nginx

瞭解Nginx

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 參數來控制它。

瞭解Nginx

用下面的語法格式:

瞭解Nginx

如果想學習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
瞭解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/> #
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP/> #
#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塊下已經包含了一些例子,通常它們是被註釋了的。

瞭解Nginx

瞭解Nginx

以/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.html

http://192.168.101.5/example.html

root指令:

瞭解Nginx

2.4. 簡單的代理服務器

首先,通過在配置文件中提那家一個或多個server塊來定義代理服務器

瞭解Nginx

上面的例子中定義了一個簡單服務器,它監聽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

瞭解Nginx

參數是一個匹配所有以.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

瞭解Nginx

一個location定義可以是一個前綴字符串,也可以是一個正則表達式。正則表達式使用的時候要在前面用“~*”修飾符(用於不區分大小寫匹配),或者“~”修飾符(用於區分大小寫)。為了找到請求匹配的location,nginx首先檢查location定義,用前綴字符串(這些location成為前綴location)。其中,最長匹配前綴的location會被選中並記住。然後,檢查正則表達式,按照它們在配置文件中出現的順序。對正則表達式的搜索在第一次匹配時終止,並使用相應的配置。如果沒有找到與正則表達式的匹配,則使用前面記住的前綴位置的配置。

畫外音:首先檢查前綴字符串,然後檢查正則表達式

1、用前綴字符串(前綴location)匹配URL,並且選中並記住最長匹配前綴的location(注意:是在匹配的裡面記住最長的那個)

2、按照正則表達式在配置文件中出現的順序依次去匹配,當匹配到第一個以後立即停止,並使用與之相應的那個location。如果沒有一個正則表達式匹配,則使用之前記住的那個前綴location。

以上,我們可以得出一個結論:優先使用正則表達式,如果沒有匹配的正則表達式發現,則使用匹配的最長前綴字符串location

)

例如:

瞭解Nginx

5. ngx_http_proxy_module模塊


ngx_http_proxy_module模塊允許將請求傳遞到另一個服務器。例如:

瞭解Nginx

5.1. proxy_pass指令

瞭解Nginx

設置代理服務器的協議和地址,以及應該映射哪一個可選URI。作為協議,可以指定“http”或“https”。地址可以指定為一個域名或IP地址,以及一個可選端口:

瞭解Nginx

如果想學習Java工程化、高性能及分佈式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java高級交流:854630135,群裡有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家。

請求URI傳遞給服務器:

如果proxy_pass指令帶一個特定的URI,那麼請求被傳給給這個服務器,正常的請求URI部分被指令中指定的URI替換,例如:

瞭解Nginx

如果proxy_pass指令不帶URI,那麼請求URI在傳遞給服務器的時候和原始請求是一樣的,例如:

瞭解Nginx

在有些情況下,請求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地址的請求處理速率。這種限制使用的是“漏桶算法”。

例如:

瞭解Nginx

6.1. limit_req指令

瞭解Nginx

設置共享內存區域和請求的最大突發大小。如果請求速率超過了為區域配置的速率,那麼它們的處理就會延遲,這樣請求就會以指定的速率進行處理。過多的請求被延遲,直到它們的數量超過最大突發大小,在這種情況下,以一個錯誤來終止請求。默認情況下,突發數量等於0。

瞭解Nginx

平均每秒不允許超過1個請求,突發不超過5個請求。

如果不希望在請求受到限制時延遲過多的請求,則應使用參數nodelay:

瞭解Nginx

可以有多個limit_req指令。例如,以下配置將限制來自單個IP地址的請求的處理速率,同時限制虛擬服務器的請求處理速率:

瞭解Nginx

6.2. limit_req_zone指令

瞭解Nginx

設置共享內存區域參數。key可以包含文本、變量、以及它們的組合。

瞭解Nginx

這個例子中,“one”這個區域維護的內存是10M,並且這個區域的平均請求處理速率不能超過每秒1個請求。

7. 控制Nginx


瞭解Nginx

8. 用Nginx作為負載均衡器


8.1. 負載均衡方法

nginx支持以下負載平衡機制(或方法):

瞭解Nginx

8.2. 默認的負載均衡配置

瞭解Nginx

如果想學習Java工程化、高性能及分佈式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java高級交流:854630135,群裡有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家。

在上面的例子彙總,同一個應用運行了3個實例。默認的負載均衡策略是循環。

8.3. 最少連接的負載均衡

另一個負載平衡原則是最少連接的。在某些請求需要更長的時間才能完成的情況下,最少連接允許更公平地控制應用程序實例上的負載。

使用連接最少的負載平衡,nginx將盡量不讓繁忙的應用服務器超載過多的請求,而是將新請求分發到不那麼繁忙的服務器。

例如:

瞭解Nginx

8.4. Session持久化

使用循環或最少連接負載平衡,每個後續客戶機的請求都可能被分發到不同的服務器。不能保證同一個客戶端總是指向同一個服務器。

使用IP-hash,客戶端的IP地址用作哈希key,以確定應該為客戶端請求選擇服務器組中的哪個服務器。此方法確保來自同一客戶端的請求總是指向同一服務器,除非該服務器不可用。

例如:

瞭解Nginx

如果想學習Java工程化、高性能及分佈式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java高級交流:854630135,群裡有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家。

8.5. 帶權重的負載均衡

還可以通過使用服務器權值進一步影響nginx的負載平衡算法。

在上面的示例中,沒有配置服務器權重,這意味著所有指定的服務器都被視為具有同等資格的特定負載平衡方法。

瞭解Nginx


分享到:


相關文章: