nginx 如何配置反向代理服務器

Nginx是一款開源代碼的高性能HTTP服務器和反向代理服務器,同時支持IMAP/POP3/SMTP代理服務,相較於Apache、lighttpd具有佔有內存少,穩定性高等優勢。

nginx 如何配置反向代理服務器


 工作原理

Nginx由內核和模塊組成,其中,內核的設計非常微小和簡潔,完成的工作也非常簡單,僅僅通過查找配置文件將客戶端請求映射到一個location block(location是Nginx配置中的一個指令,用於URL匹配),而在這個location中所配置的每個指令將會啓動不同的模塊去完成相應的工作。

Nginx的模塊從結構上分爲核心模塊、基礎模塊和第三方模塊:

  • 核心模塊:HTTP模塊、EVENT模塊和MAIL模塊
  • 基礎模塊:HTTP Access模塊、HTTP FastCGI模塊、HTTP Proxy模塊和HTTP Rewrite模塊,
  • 第三方模塊:HTTP Upstream Request Hash模塊、Notice模塊和HTTP Access Key模塊。

用戶根據自己的需要開發的模塊都屬於第三方模塊。正是有了這麼多模塊的支撐,Nginx的功能纔會如此強大。

Nginx的模塊從功能上分爲如下三類。

  • Handlers(處理器模塊)。此類模塊直接處理請求,並進行輸出內容和修改headers信息等操作。Handlers處理器模塊一般只能有一個。
  • Filters (過濾器模塊)。此類模塊主要對其他處理器模塊輸出的內容進行修改操作,最後由Nginx輸出。
  • Proxies (代理類模塊)。此類模塊是Nginx的HTTP Upstream之類的模塊,這些模塊主要與後端一些服務比如FastCGI等進行交互,實現服務代理和負載均衡等功能。

 

Nginx本身做的工作實際很少,當它接到一個HTTP請求時,它僅僅是通過查找配置文件將此次請求映射到一個location block,而此location中所配置的各個指令則會啓動不同的模塊去完成工作,因此模塊可以看做Nginx真正的勞動工作者。通常一個location中的指令會涉及一個handler模塊和多個filter模塊(當然,多個location可以複用同一個模塊)。handler模塊負責處理請求,完成響應內容的生成,而filter模塊對響應內容進行處理。

Nginx的模塊直接被編譯進Nginx,因此屬於靜態編譯方式。啓動Nginx後,Nginx的模塊被自動加載,不像Apache,首先將模塊編譯爲一個so文件,然後在配置文件中指定是否進行加載。在解析配置文件時,Nginx的每個模塊都有可能去處理某個請求,但是同一個處理請求只能由一個模塊來完成。

Nginx 的進程模型

在工作方式上,Nginx分爲單工作進程和多工作進程兩種模式。在單工作進程模式下,除主進程外,還有一個工作進程,工作進程是單線程的;在多工作進程模式下,每個工作進程包含多個線程。Nginx默認爲單工作進程模式。

Nginx在啓動後,會有一個master進程和多個worker進程。

master進程

主要用來管理worker進程,包含:接收來自外界的信號,向各worker進程發送信號,監控worker進程的運行狀態,當worker進程退出後(異常情況下),會自動重新啓動新的worker進程。

master進程充當整個進程組與用戶的交互接口,同時對進程進行監護。它不需要處理網絡事件,不負責業務的執行,只會通過管理worker進程來實現重啓服務、平滑升級、更換日誌文件、配置文件實時生效等功能。

我們要控制nginx,只需要通過kill向master進程發送信號就行了。比如kill -HUP pid,則是告訴nginx,從容地重啓nginx,我們一般用這個信號來重啓nginx,或重新加載配置,因爲是從容地重啓,因此服務是不中斷的。master進程在接收到HUP信號後是怎麼做的呢?首先master進程在接到信號後,會先重新加載配置文件,然後再啓動新的worker進程,並向所有老的worker進程發送信號,告訴他們可以光榮退休了。新的worker在啓動後,就開始接收新的請求,而老的worker在收到來自master的信號後,就不再接收新的請求,並且在當前進程中的所有未處理完的請求處理完成後,再退出。當然,直接給master進程發送信號,這是比較老的操作方式,nginx在0.8版本之後,引入了一系列命令行參數,來方便我們管理。比如,./nginx -s reload,就是來重啓nginx,./nginx -s stop,就是來停止nginx的運行。如何做到的呢?我們還是拿reload來說,我們看到,執行命令時,我們是啓動一個新的nginx進程,而新的nginx進程在解析到reload參數後,就知道我們的目的是控制nginx來重新加載配置文件了,它會向master進程發送信號,然後接下來的動作,就和我們直接向master進程發送信號一樣了。

worker進程:

而基本的網絡事件,則是放在worker進程中來處理了。多個worker進程之間是對等的,他們同等競爭來自客戶端的請求,各進程互相之間是獨立的。一個請求,只可能在一個worker進程中處理,一個worker進程,不可能處理其它進程的請求。worker進程的個數是可以設置的,一般我們會設置與機器cpu核數一致,這裏面的原因與nginx的進程模型以及事件處理模型是分不開的。

worker進程之間是平等的,每個進程,處理請求的機會也是一樣的。當我們提供80端口的http服務時,一個連接請求過來,每個進程都有可能處理這個連接,怎麼做到的呢?首先,每個worker進程都是從master進程fork過來,在master進程裏面,先建立好需要listen的socket(listenfd)之後,然後再fork出多個worker進程。所有worker進程的listenfd會在新連接到來時變得可讀,爲保證只有一個進程處理該連接,所有worker進程在註冊listenfd讀事件前搶accept_mutex,搶到互斥鎖的那個進程註冊listenfd讀事件,在讀事件裏調用accept接受該連接。當一個worker進程在accept這個連接之後,就開始讀取請求,解析請求,處理請求,產生數據後,再返回給客戶端,最後才斷開連接,這樣一個完整的請求就是這樣的了。我們可以看到,一個請求,完全由worker進程來處理,而且只在一個worker進程中處理。worker進程之間是平等的,每個進程,處理請求的機會也是一樣的。當我們提供80端口的http服務時,一個連接請求過來,每個進程都有可能處理這個連接,怎麼做到的呢?首先,每個worker進程都是從master進程fork過來,在master進程裏面,先建立好需要listen的socket(listenfd)之後,然後再fork出多個worker進程。所有worker進程的listenfd會在新連接到來時變得可讀,爲保證只有一個進程處理該連接,所有worker進程在註冊listenfd讀事件前搶accept_mutex,搶到互斥鎖的那個進程註冊listenfd讀事件,在讀事件裏調用accept接受該連接。當一個worker進程在accept這個連接之後,就開始讀取請求,解析請求,處理請求,產生數據後,再返回給客戶端,最後才斷開連接,這樣一個完整的請求就是這樣的了。我們可以看到,一個請求,完全由worker進程來處理,而且只在一個worker進程中處理。

nginx的進程模型,可以由下圖來表示:


 

 Nginx+FastCGI運行原理

FastCGI是一個可伸縮地、高速地在HTTP server和動態腳本語言間通信的接口。多數流行的HTTP server都支持FastCGI,包括Apache、Nginx和lighttpd等。同時,FastCGI也被許多腳本語言支持,其中就有PHP。

 FastCGI接口方式採用C/S結構,可以將HTTP服務器和腳本解析服務器分開,同時在腳本解析服務器上啓動一個或者多個腳本解析守護進程。當HTTP服務器每次遇到動態程序時,可以將其直接交付給FastCGI進程來執行,然後將得到的結果返回給瀏覽器。這種方式可以讓HTTP服務器專一地處理靜態請求或者將動態腳本服務器的結果返回給客戶端,這在很大程度上提高了整個應用系統的性能。

Nginx是個輕量級的HTTP server,必須藉助第三方的FastCGI處理器纔可以對PHP進行解析,因此其實這樣看來nginx是非常靈活的,它可以和任何第三方提供解析的處理器實現連接從而實現對PHP的解析(在nginx.conf中很容易設置)。

 


Nginx 配置文件


配置文件主要由四部分組成:main(全區設置),server(主機配置),upstream(負載均衡服務器設置),和location(URL匹配特定位置設置)。

1)全局變量

複製代碼
#Nginx的worker進程運行用戶以及用戶組
user  nobody nobody;
#Nginx開啓的進程數,建議爲CPU的核數 worker_processes
1; #worker_processes auto;
#以下參數指定了哪個cpu分配給哪個進程,一般來說不用特殊指定。如果一定要設的話,用0和1指定分配方式. #這樣設就是給1
-4個進程分配單獨的核來運行,出現第5個進程是就是隨機分配了。eg: worker_processes 4 #4核CPU worker_cpu_affinity 0001 0010 0100 1000 #定義全局錯誤日誌定義類型,[debug|info|notice|warn|crit] error_log logs/error.log info;
#指定進程ID存儲文件位置 #pid logs
/nginx.pid;
#一個nginx進程打開的最多文件描述符數目,理論值應該是最多打開文件數(ulimit
-n)與nginx進程數相除,但是nginx分配請求並不是那麼均勻,所以最好與ulimit -n的值保持一致。 #vim /etc/security/limits.conf # * soft nproc 65535 # * hard nproc 65535 # * soft nofile 65535 # * hard nofile 65535 worker_rlimit_nofile 65535;
複製代碼

2)事件配置


events {
    #use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本內核中的高性能網絡I/O模型,如果跑在FreeBSD上面,就用kqueue模型。
    use epoll;
#每個進程可以處理的最大連接數,理論上每臺nginx服務器的最大連接數爲worker_processes
*worker_connections。理論值:worker_rlimit_nofile/worker_processes #注意:最大客戶數也由系統的可用socket連接數限制(~ 64K),所以設置不切實際的高沒什麼好處 worker_connections 65535;
#worker工作方式:串行(一定程度降低負載,但服務器吞吐量大時,關閉使用並行方式) #multi_accept on; }

3)http參數 https://www.7428.com.cn


    #文件擴展名與文件類型映射表
    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"';
#定義日誌的格式。後面定義要輸出的內容。 #
1.$remote_addr 與$http_x_forwarded_for 用以記錄客戶端的ip地址; #2.$remote_user :用來記錄客戶端用戶名稱; #3.$time_local :用來記錄訪問時間與時區; #4.$request :用來記錄請求的url與http協議; #5.$status :用來記錄請求狀態; #6.$body_bytes_sent :記錄發送給客戶端文件主體內容大小; #7.$http_referer :用來記錄從那個頁面鏈接訪問過來的; #8.$http_user_agent :記錄客戶端瀏覽器的相關信息
#連接日誌的路徑,指定的日誌格式放在最後。 #access_log logs
/access.log main;
#只記錄更爲嚴重的錯誤日誌,減少IO壓力 error_log logs
/error.log crit; #關閉日誌 #access_log off; #默認編碼 #charset utf-8;
#服務器名字的hash表大小 server_names_hash_bucket_size
128;
#客戶端請求單個文件的最大字節數 client_max_body_size 8m;
#指定來自客戶端請求頭的hearerbuffer大小 client_header_buffer_size 32k;
#指定客戶端請求中較大的消息頭的緩存最大數量和大小。 large_client_header_buffers
4 64k;
#開啓高效傳輸模式。 sendfile on;
#防止網絡阻塞 tcp_nopush on; tcp_nodelay on;
#客戶端連接超時時間,單位是秒 keepalive_timeout
60;
#客戶端請求頭讀取超時時間 client_header_timeout
10;
#設置客戶端請求主體讀取超時時間 client_body_timeout
10;
#響應客戶端超時時間 send_timeout
10; #FastCGI相關參數是爲了改善網站的性能:減少資源佔用,提高訪問速度。 fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 128k; #gzip模塊設置 #開啓gzip壓縮輸出 gzip on; #最小壓縮文件大小 gzip_min_length 1k; #壓縮緩衝區 gzip_buffers 4 16k; #壓縮版本(默認1.1,前端如果是squid2.5請使用1.0) gzip_http_version 1.0; #壓縮等級 1-9 等級越高,壓縮效果越好,節約寬帶,但CPU消耗大 gzip_comp_level 2; #壓縮類型,默認就已經包含text/html,所以下面就不用再寫了,寫上去也不會有問題,但是會有一個warn。 gzip_types text/plain application/x-javascript text/css application/xml; #前端緩存服務器緩存經過壓縮的頁面 gzip_vary on;

4)虛擬主機基本配置


#虛擬主機定義
    server {
        #監聽端口
        listen       80;
#訪問域名 server_name localhost;
#編碼格式,若網頁格式與此不同,將被自動轉碼 #charset koi8
-r;
#虛擬主機訪問日誌定義 #access_log logs
/host.access.log main;
#對URL進行匹配 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; } #訪問URL以.php結尾則自動轉交給127.0.0.1 # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #}
#php腳本請求全部轉發給FastCGI處理 # 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; #} #禁止訪問.ht頁面 (需ngx_http_access_module模塊) # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } #HTTPS虛擬主機定義 # 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; # } #}

5)Nginx狀態監控


#Nginx運行狀態,StubStatus模塊獲取Nginx自啓動的工作狀態(編譯時要開啓對應功能)
        #location /NginxStatus {
        #    #啓用StubStatus的工作訪問狀態    
        #    stub_status    on;
        #    #指定StubStaus模塊的訪問日誌文件
        #    access_log    logs/Nginxstatus.log;
        #    #Nginx認證機制(需Apache的htpasswd命令生成)
        #    #auth_basic    "NginxStatus";
        #    #用來認證的密碼文件
        #    #auth_basic_user_file    ../htpasswd;    
        #}
訪問:http://IP/NginxStatus(測試就不加密碼驗證相關) 

6)反向代理 


#以下配置追加在HTTP的全局變量中

#nginx跟後端服務器連接超時時間(代理連接超時)
proxy_connect_timeout      5;
#後端服務器數據回傳時間(代理髮送超時) proxy_send_timeout
5;
#連接成功後,後端服務器響應時間(代理接收超時) proxy_read_timeout
60;
#設置代理服務器(nginx)保存用戶頭信息的緩衝區大小 proxy_buffer_size 16k;
#proxy_buffers緩衝區,網頁平均在32k以下的話,這樣設置 proxy_buffers
4 32k;
#高負荷下緩衝大小(proxy_buffers
*2) proxy_busy_buffers_size 64k;
#設定緩存文件夾大小,大於這個值,將從upstream服務器傳 proxy_temp_file_write_size 64k;
#反向代理緩存目錄 proxy_cache_path
/data/proxy/cache levels=1:2 keys_zone=cache_one:500m inactive=1d max_size=1g;
#levels
=1:2 設置目錄深度,第一層目錄是1個字符,第2層是2個字符 #keys_zone:設置web緩存名稱和內存緩存空間大小 #inactive:自動清除緩存文件時間。 #max_size:硬盤空間最大可使用值。
#指定臨時緩存文件的存儲路徑(路徑需和上面路徑在同一分區) proxy_temp_path
/data/proxy/temp #服務配置 server { #偵聽的80端口 listen 80; server_name localhost; location / { #反向代理緩存設置命令(proxy_cache zone|off,默認關閉所以要設置) proxy_cache cache_one; #對不同的狀態碼緩存不同時間 proxy_cache_valid 200 304 12h; #設置以什麼樣參數獲取緩存文件名 proxy_cache_key $host$uri$is_args$args; #後7端的Web服務器可以通過X-Forwarded-For獲取用戶真實IP proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #代理設置 proxy_pass http://IP; #文件過期時間控制 expires 1d; } #配置手動清楚緩存(實現此功能需第三方模塊 ngx_cache_purge) #https://www.3669.com.cn/bzj1/訪問 #https://www.3669.com.cn/bzj2/清楚URL緩存 location ~ /purge(/.*) { allow 127.0.0.1; deny all; proxy_cache_purge cache_one $host$1$is_args$args; } #設置擴展名以.jsp、.php、.jspx結尾的動態應用程序不做緩存 location ~.*\.(jsp|php|jspx)?$ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://http://IP; }

7)負載均衡


#負載均衡服務器池
upstream my_server_pool {
    #調度算法
    #1.輪循(默認)(weight輪循權值)
    #2.ip_hash:根據每個請求訪問IP的hash結果分配。(會話保持)
    #3.fair:根據後端服務器響應時間最短請求。(upstream_fair模塊)
    #4.url_hash:根據訪問的url的hash結果分配。(需hash軟件包)
    #參數:
    #down:表示不參與負載均衡
    #backup:備份服務器
    #max_fails:允許最大請求錯誤次數
    #fail_timeout:請求失敗後暫停服務時間。
    server 192.168.1.109:80 weight=1 max_fails=2 fail_timeout=30;
    server 192.168.1.108:80 weight=2 max_fails=2 fail_timeout=30;
}
#負載均衡調用
server {
    ...
    location / {
    proxy_pass http://my_server_pool;
    }
}

8)URL重寫 (https://www.3669.com.cn


  #根據不同的瀏覽器URL重寫
  if($http_user_agent ~ Firefox){
  rewrite ^(.*)$ /firefox/$1 break; 
  }
  if($http_user_agent ~ MSIE){
  rewrite ^(.*)$ /msie/$1 break; 
  }

  #實現域名跳轉
  location / {
  rewrite ^/(.*)$ https://web8.example.com$1 permanent;
  }


9)IP限制


#限制IP訪問
location / {
    deny 192.168.0.2;
    allow 192.168.0.0/24;
    allow 192.168.1.1;
    deny all;
}

來自未來智庫 https://www.7428.cn

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章