文章參考:https://blog.csdn.net/physicsdandan/article/details/45667357php
什麼是代理?html
代理在普通生活中的意義就是原本應該你作的事情,你讓別人代你作了,那麼那個幫你作的人就是你的代理。和在計算機網絡中代理的概念差很少,前端
原本是要客戶端作的網絡訪問,如今移交給另一臺機器作,那麼那個機器就被稱爲代理服務器,代理服務器幫你訪問。過程以下:node
正常狀況:linux
client-(send request)->serverios
代理狀況:nginx
client-(send request)->client proxy(send request)->serverweb
什麼是反向代理?正則表達式
反向代理在計算機網絡中是指這麼一個過程,通常來講正向代理是客戶端找人來代理把本身的請求轉發給服務器,可是若是是反向代理,找代理的人再也不算法
是客戶端,而是服務端這邊把本身接受的請求轉發給背後的其餘機器。
反向代理狀況:
client-(send request)->server proxy(send request)->other server
下面看一個示例:
#① part start #運行nginx進程的帳戶 user www; # worker_process 1; error_log /var/log/nginx/error.log pid /var/run/nginx.pid; events{ use epoll; worker_connections 1024; } http{ include /etc/nginx/mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log main; # sendfile on; # keepalive_timeout 65; gzip on; index index.html index.htm; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; #② part start # 定義上游服務器列表組 upstream web1 { server 127.0.0.1:111 weight=1; server 127.0.0.1:222 weight=1; } upstream web2 { server 127.0.0.2:111 weight=1; server 127.0.0.2:222 weight=6; server 127.0.0.2:333 weight=7; } #定義一個服務器,其監聽80端口,配置的域名是www.company.com server{ listen 80; # using www domain to access the main website server_name www.company.com; access_log /var/log/nginx/www.log location / { root /home/website_root; } } #③ part start #定義第二個服務器,其一樣監聽80端口,可是匹配域名是web.company.com server{ listen 80; # using web sub domain to access server_name web.company.com; access_log /var/log/nginx/web_access.log location / { root /home/web2_root; proxy_pass http://127.0.0.1:8080/web/; proxy_read_timeout 300; proxy_connect_timeout 300; proxy_redirect off; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; } } #定義第三個服務器,其一樣監聽80端口,可是匹配域名是web1.company.com,並把請求轉發到web1上游服務 server{ listen 80; # using web1 sub domain to access server_name web1.company.com; access_log /var/log/nginx/web1_access.log location / { root /home/web1_root; proxy_pass http://web1; proxy_read_timeout 300; proxy_connect_timeout 300; proxy_redirect off; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; } } #定義第三個服務器,其一樣監聽80端口,可是匹配域名是web2.company.com,並把請求轉發到web2上游服務 server{ listen 80; # using web2 sub domain to access server_name web2.company.com; access_log /var/log/nginx/web2_access.log location / { root /home/web2_root; proxy_pass http://web2; proxy_read_timeout 300; proxy_connect_timeout 300; proxy_redirect off; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; } } }
這個示例都作了什麼?
1.第一部分,定義了 nginx 通用規則
2.第二部分,開始定義上游服務器組
3.第三部分,開始定義 server,並指定如何使用第二部分定義的 upstream
整體來講上面的示例提供了四個服務,www、web、web一、web2 4個網站,這個例子很適合一臺機器,可是又想避免訪問 url 中帶有端口號,統一使用
域名方式訪問。4個網站都監聽 80 端口,可是分配不一樣的二級域名便可。這就須要 nginx 反向代理,具體如何實現,咱們從新舉一個例子,以下所示:
(1) 只有一臺服務器,一個 IP,一個域名 www.xsgzs.com
(2) 這臺服務器上有多個應用運行在不一樣端口,如:
127.0.0.1:4000 運行着一個 博客應用
127.0.0.1:3009 運行着一個博客後臺管理系統
咱們不指望在訪問的 url 中攜帶有端口號,統一使用域名方式訪問,能夠爲運行在不一樣端口號的應用分配二級域名,同時把二級域名都解析到 80 端口,
可是轉發到不一樣的端口去,但願訪問 www.blog.xsgzs.com 能訪問到 127.0.0.1:4000 ,訪問 www.admin.xsgzs.com 能訪問到 127.0.0.1:3009
具體步驟:
(1) 在 nginx.conf 文件新增 upstream server(上游服務器)
upstream blog.xsgzs { server 127.0.0.1:4000 } upstream admin.xsgzs { server 127.0.0.1:3009 }
(2) 在配置文件中添加 server,都監聽 80 端口
server { listen 80; server_name www.blog.xsgzs.com; location / { proxy_pass http://blog.xsgzs; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } server { listen 80; server_name www.admin.xsgzs.com; location / { proxy_pass http://admin.xsgzs; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
爲何須要反向代理?
做爲服務端代理,天然是一臺機器處理不過來了,須要轉發、分散請求給其餘服務器作。下面列出一些適用場景:
1.負載均衡:
上面的例子1中 web1 和 web2 上游服務器組都使用了負載均衡,把請求轉發向一組服務器。具體轉發給哪臺服務器,nginx 提供了多種負載均衡策略,上面使用的是加權方式
2.一個域名,多個網站。 如上面的例2
3.反向代理另外一個做用就是隱藏後面的真實服務,以此達到必定的安全性
仔細講解各個模塊
nginx 配置文件主要分爲六個區域
(1) main 全局設置 (2) events (nginx 工做模式) (3) http (http設置) (4) server (主機設置) (5) location (URL匹配) (6) upstream (負載均衡服務器設置)
main 模塊(全局設置)
下面是一個 main 區域,它是一個全局設置
user nobody nobody; worker_processes 2; error_log /usr/local/var/log/nginx/error.log notice; worker_rlimit_nofile 1024;
user 用來設置運行 nginx 服務器的用戶或用戶組,語法格式:
user user [group]
user , 指定能夠運行 nginx 服務器的用戶
group,可選項,指定能夠運行 nginx 服務器的用戶組
注:只有被指定的用戶或用戶組纔有權限啓動 nginx 進程,若是是其餘用戶 (test_user) 嘗試啓動 nginx 進程,將會報錯
nginx: [emerg] getpwnam("test_user") failed (2:No such file or directory) in /Nginx/conf/nginx.conf:2
從上面的報錯信息中能夠知道,nginx 沒法運行的緣由是查找 test_user 失敗,引發錯誤的緣由在 nginx.conf 文件第二行即
配置運行 nginx 服務器的用戶或用戶組
若是但願全部的用戶或用戶組都有權限啓動 nginx 進程,有兩種方式:一是將此行指令註釋掉、而是將用戶或用戶組設置
爲 nobody,這也是 user 指令的默認值
worker_processes 用來指定 nginx 要開啓的子進程數目
worker prcocess 是 nginx 服務器實現併發處理的關鍵所在,從理論上來講,worker process 的值越大,能夠支持的併發處理量越大,但實際上它還要受到來自軟件自己、
操做系統自己資源和能力、硬件設備(如:CPU 和 磁盤驅動器)等制約,其語法格式:
worker_processes number | auto
number,來指定 nginx 要開啓的子進程數目
auto,nginx 自動檢測
在默認配置文件中,number = 1,啓動 nginx 服務器以後,使用如下命令能夠看到此時的 nginx 除了主進程 master process 以外還生成了一個 worker process,在這裏我將
number 指定爲 4 ,除了主進程 master process 以外還生成了 4 個 worker process
在這裏還有一點須要注意的地方:
worker_processes 指的是操做系統啓動多少個工做進程運行 nginx,注意這裏說的是工做進程(worker process)。在 nginx 運行的時候,會啓動兩種進程,一種進程是 master pro
cess(主進程),一種是 worker process(工做進程)。主進程負責監控端口,協調工做進程的工做狀態,分配工做任務,工做進程負責進行任務處理,通常這個參數要和操做系統 CPU 內
核數成倍數。
error_log 關於錯誤日誌的配置能夠參考這一篇文章:https://www.cnblogs.com/leeyongbard/p/10880356.html
worker_rlimit_nofile 用來設定一個 nginx worker process (工做進程),可打開最大文件數
events 模塊
events 模塊用來指定 nginx 的工做模式以及每個 worker process 同時開啓的最大鏈接數,以下:
events { use epoll; #Linux平臺 worker_connections 1024; }
use 用來指定 nginx 的工做模式,nginx 支持的工做模式有:select、poll、Kqueue、epoll、rtsig 和 /dev/poll,select 和 poll 是標準的工做模式,Kqueue 和 epoll 是
高效的工做模式,不一樣的是 epoll 是用在 linux 平臺,而 Kqueue 是用在 BSD 系統,而 mac 基於 BSD ,因此 mac 上的 nginx 工做模式是 Kqueue ,epoll 是 Linux 上nginx
工做模式的首選
worker_connections 用來設置容許每個 worker process 同時開啓的最大鏈接數,即接收前端的最大請求數。最大客戶端鏈接數由 worker_processes 和 worker_conn
ectios決定,即 max_clients = worker_processes * worker_connections ,在做爲反向代理時,max_clients = worker_processes * worker_connections/4。注意,一個進程建
立一個鏈接後,進程將打開一個文件副本。因此,worker_connections 的 number 值還受到操做系統設定的,進程最大可打開文件數
其語法格式:
worker_connections number
設置 nginx 進程最大可打開文件數(不能超過系統級別設定的進程可打開最大文件數)
1.更改系統級別 "進程可打開最大文件數"
首先須要要有 root 權限,修改 /etc/security/limits.conf
在主配置文件中添加下面兩句
* soft nofile 327680 * hard nofile 327680
soft 表示應用軟件級別限制的最大可打開文件數,hard 表示操做系統級別限制的最大可打開文件數,"*" 表示對全部用戶都生效
保存配置不會當即生效,須要經過 ulimit 命令 或 重啓系統
ulimit -n 327680
執行命令後,經過 ulimit -a 查看修改是否生效
core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 63704 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 327680 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 10240 cpu time (seconds, -t) unlimited max user processes (-u) 63704 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
注意,open files 這一項變化了表示修改生效
2. 修改 nginx 軟件級別的 "進程最大可打開文件數"
第一步只是修改了操做系統級別的 "進程最大可打開文件數",做爲 nginx 來講,咱們還須要對這個軟件進行修改,打開 nginx.conf 主配置文件,修改 worker_rlimit_nofile 屬性
修改完成以後,須要重啓 nginx 配置才能生效
3.驗證 nginx 的 "進程最大可打開文件數" 是否生效
在 Linux 中,全部的進程都會有一個臨時的核心配置文件描述,存放位置:/pro/進程號/limit
咱們能夠看到,nginx worker process 的進程號分別是:487二、487三、487四、4875,咱們選擇其中一個查看其核心配置信息:
能夠看到 Max open files 分別是65535,更改配置信息後,重啓 nginx,如上所示方式查看是否生效
http 模塊
http 模塊能夠說是最核心的模塊了,它主要負責 HTTP 服務器相關屬性的配置,它裏面的 server、upstream 相當重要,下面看一個簡單的 http 模塊配置
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 /usr/local/var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 10; #gzip on; upstream myproject { ..... } server { .... } }
說一下每一個配置項的具體含義
include:nginx 服務器做爲 web 服務器,必須可以識別前端請求過來的資源類型,include mime.types 用來設置 nginx 所能識別的文件類型,mime.types 在
nginx 主配置文件同級目錄下
default_type:設置默認的類型爲二進制流,也就是當請求的資源類型在 mime.types 裏面未定義時默認使用該類型
access_log、log_format 能夠參考這篇文章:https://www.cnblogs.com/leeyongbard/p/10880356.html
sendfile 用於開啓高效的文件傳輸模式。將 tcp_nopush、tcp_nodelay 設置爲 on 用於防止網絡阻塞
keepalive_timeout:用於設置與用戶創建鏈接以後,nginx 服務器能夠保持這些鏈接一段時間
server 模塊
server 模塊是 http 模塊的子模塊,主要用於定義一個虛擬主機,下面先看一個簡單的 server 是如何作的?
server { listen 8080; server_name localhost 192.168.12.10 www.yangyi.com; # 全局定義,若是都是這一個目錄,這樣定義最簡單。 root /Users/yangyi/www; index index.php index.html index.htm; charset utf-8; access_log usr/local/var/log/host.access.log main; error_log usr/local/var/log/host.error.log error; .... }
server,標誌定義虛擬主機開始
listen,指定虛擬主機的服務端口
server_name,用來指定 IP 地址或 域名,多個域名之間用空格分開
root,配置請求的根目錄
web 服務器在接收到網絡請求後,須要在服務端指定的根目錄中尋找請求的資源。在 nginx 服務器中 root 指令就是設置這個根目錄的,其語法爲:
root path
path 爲 nginx 服務器接收到請求後查找資源的根目錄。root 指令能夠在 http,server,location 塊中均可以配置,多數狀況下 root 指令是配置在 location
塊中,看一個簡單的示例
location /data/ { root /locationtest1; }
當 location 塊接收到 /data/index.html 的請求時,將會在 /locationtest1/data/ 目錄下尋找 index.html 響應請求
index,用於設定只輸入域名時訪問的默認首頁地址,有個前後順序:index.php、index.html、index.htm 若是沒有開啓目錄瀏覽權限,又找不到這些默認首頁,則會報 403
charset,設置網頁的默認編碼格式
access_log,error_log 這裏再也不說
location 模塊
location 模塊也是一個很是重要且經常使用的模塊,根據字面意思就能夠知道主要用於定位,定位 URL,解析 URL,它提供了很是強大的正則匹配功能,也支持條件判斷匹配
在 nginx 官方文檔中定義的 location 語法爲:
location [ = | ~ | ~* | ^~] uri { ................ ................ }
其中,uri 是待匹配的請求字符串,能夠是不含正則表達式的字符串,如,/myserver.php,也能夠是包含正則表達式的字符串,如,.php$(表示以 .php 結尾)
不包含正則表達式的 uri -> 標準 uri
包含正則表達式的 uri -> 正則 uri
方括號裏面的部分是可選項,在介紹四種標識以前先了解下若是不添加此選項時,nginx 服務器是如何在 server 塊中搜索並使用 location 塊和 uri 實現和請求字符串匹配的
在不添加此選項時,nginx 服務器會在 server 塊的多個 location 塊中搜索是否有和標準 uri 匹配的請求字符串,若是有多個能夠匹配,就記錄匹配度最高的一個。而後再用
location 塊中的正則 uri 和請求字符串匹配,當正則 uri 匹配成功以後,結束搜索,使用此 location 塊處理請求。若是正則 uri 匹配失敗,就是用上面匹配度最高的 location
塊處理此請求。
四種標識(=、~、~*、^~)
1. =,用於標準 uri 前,要求請求字符串和 uri 嚴格匹配。若是匹配成功,就中止向下繼續搜索並當即使用該 location 塊處理請求 2,~,用於表示 uri 包含正則表達式,並區分大小寫 3,~*,用於表示 uri 包含正則表達式,而且不區分大小寫 4,^~,用於標準 uri 前,要求 nginx 服務器找到和請求字符串匹配度最高的標準 uri 後,當即使用該 location 快處理請求,再也不使用 location 塊的正則 uri 和請求字符串作匹配
注意:
咱們知道瀏覽器傳送 uri 時,會對一部分 uri 進行編碼,好比,空格會被編碼成 "%20",問號會被編碼成 '%3f"等,"^"有一個特色,它會對 uri 中的這些符號作編碼處理,如,若是 location 塊接收到的 uri 是 /html/%20/data,則當 nginx 服務器搜索到配置爲 /html//data 的 location 塊時就能夠匹配成功
upstream 模塊
upstream 模塊負責負載均衡,目前 nginx 的負載均衡支持 4 種方式:
1,輪詢(默認)
每一個請求按照時間順序逐一分配到不一樣後端服務器,若是後端服務器 down 掉,則自動剔除,使用戶訪問不受影響
2,weight(指定輪詢權重)
weight 的值越大分配到的訪問機率越高,主要用於後端每臺服務器性能不均衡的狀況下,或僅僅在主從狀況下設置不一樣的權值,達到有效合理的利用主機資源。
upstream bakend { server 192.168.0.14 weight=10; server 192.168.0.15 weight=10; }
3,ip_hash
每一個請求按照訪問 ip 的哈希結果分配,使來自同一個 ip 的訪客固定訪問一臺後端服務器
upstream bakend { ip_hash; server 192.168.0.14:88; server 192.168.0.15:80; }
4,fair
比 weight、ip_hash 更加智能的負載均衡算法,fair 能夠根據頁面大小和加載時間長短智能地進行負載均衡,也就是根據後端服務器的響應時間來分配請求,響應時間
的優先分配。nginx 自己並不支持 fair,若是要使用這種調度算法,則須要安裝 upstream_fair 模塊。
upstream backend { server server1; server server2; fair; }
4,url_hash
按照訪問 url 的哈希結果分配,使每個 url 定向到後端某一臺服務器,能夠進一步提升後端緩存服務器的效率,不過 nginx 自己是不支持這種調度算法的,須要安裝
nginx 的 hash 軟件包
例:在upstream中加入hash語句,server語句中不能寫入weight等其餘的參數,hash_method是使用的hash算法 upstream backend { server squid1:3128; server squid2:3128; hash $request_uri; hash_method crc32; }
在 nginx 的 upstream 模塊,能夠設置每臺後端服務器在負載均衡中的調度狀態,經常使用的狀態:
1,down,表示當前機器暫時不參與負載均衡 2,backup,預留的備份機器。當其餘全部的非 backup 機器出現故障或忙的時候,纔會請求 backup 機器,由於此臺機器的訪問壓力最小 3,max_fails,容許請求的失敗次數,默認爲 1,當超過最大次數時,返回 proxy_next_upstream 模塊定義的錯誤 4,fail_timeout,請求失敗超時時間,在經歷了 max_fails 次失敗後,暫停服務的時間。max_fails 和 fail_timeout 能夠一塊兒使用
下面看一個簡單的 upstream 模塊配置:
1,在 http 節點下添加 upstream 節點
upstream linuxidc { server 10.0.6.108:7080; server 10.0.0.85:8980; }
2,將 server 節點下的 location 節點中的 proxy_pass 配置爲:http:// + upstream名稱
location / { root hml; index index.html index.htm; proxy_pass http://linuxidc; }
如今負載均衡初步完成了,upstream 按照輪詢(默認)方式進行負載均衡。