nginx 反向代理配置(一)


      文章參考:https://blog.csdn.net/physicsdandan/article/details/45667357

      什么是代理?

      代理在普通生活中的意義就是本來應該你做的事情,你讓別人代你做了,那么那個幫你做的人就是你的代理。和在計算機網絡中代理的概念差不多,

本來是要客戶端做的網絡訪問,現在移交給另外一台機器做,那么那個機器就被稱為代理服務器,代理服務器幫你訪問。過程如下:

      正常情況:

      client-(send request)->server

      代理情況:

      client-(send request)->client proxy(send request)->server

      什么是反向代理?

      反向代理在計算機網絡中是指這么一個過程,一般來說正向代理是客戶端找人來代理把自己的請求轉發給服務器,但是如果是反向代理,找代理的人不再

是客戶端,而是服務端這邊把自己接受的請求轉發給背后的其他機器。

     反向代理情況:

     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、web1、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 的進程號分別是:4872、4873、4874、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 按照輪詢(默認)方式進行負載均衡。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM