Nginx使用及可能遇到問題

最近有一個項目要部署到線上服務器,花了幾天時間終於把所有的問題都完美解決了。在部署期間遇到一些與nginx相關問題及解決方法一併記錄了下來。   

                             

目錄

1 nginx概述

1.1 nginx簡介

1.2 nginx下載

1.2.1 windows下載

1.2.2 Linux下載

1.3 啓動測試

1.3.1 windows環境

1.3.2 linux環境

1.4 常用命令

2 nginx配置

2.1 一個簡單例子

2.2 語句含義

2.3 重要模塊

2.3.1 負載均衡

2.3.2 代理/反向代理

3 可能遇到的問題

3.1 nginx配置後,只有一個頁面(首頁)能正常訪問,其他頁面全加載不出來

3.1.1描述

3.1.2 解決

3.2 Nginx報錯"no live upstreams while connecting to upstream",錯誤碼502

3.2.1 描述

3.2.2 解決

3.3 用nginx進行負載均衡時,web項目的session共享問題

3.3.1 描述

3.3.2 解決

3.4 服務器上配置好nginx後,用兩臺電腦訪問,總是命中後臺某一個服務器

3.4.1 描述

3.4.2 解決

3.5 要對某些代理做驗證

3.5.1 描述

3.5.2 解決

4 參考資料


 

 

1 nginx概述

1.1 nginx簡介

Nginx是俄羅斯人Igor Sysoev編寫的輕量級Web服務器,它的發音爲 [ˈendʒɪnks] ,它不僅是一個高性能的HTTP和反向代理服務器,同時也是一個IMAP/POP3/SMTP 代理服務器。

通常是用來做代理/反向代理,負載均衡的。至於它的特點優點這裏不再贅述,我們重點看它的用法和可能遇到問題的解決方案。

1.2 nginx下載

1.2.1 windows下載

windows下載地址:http://nginx.org/en/download.html,點擊進去如下圖:

1.2.2 Linux下載

方式一

和Windows同樣的地址http://nginx.org/en/download.html,點擊進去如下圖:

 

方式二

從網站去去下載,http://nginx.org/download/,如下圖:

 

方式三

在linux環境下安裝,在下面網頁中有詳細介紹

https://jingyan.baidu.com/article/e3c78d648516243c4c85f5c2.html

1.3 啓動測試

1.3.1 windows環境

下載後,如下圖:

進入nginx-1.16.1目錄後,雙擊nginx.exe,有個窗口會一閃而過,在瀏覽器中輸入localhost,如下圖:

說明nginx正常啓動了。

1.3.2 linux環境

也很簡單,這裏不再贅述,詳情可以參照:https://jingyan.baidu.com/article/e3c78d648516243c4c85f5c2.html

啓動成功後,也會有歡迎頁面,若不成功注意防火牆對默認監聽端口80的攔截,要開放這個端口。

1.4 常用命令

nginx -s stop       # 快速關閉Nginx,可能不保存相關信息,並迅速終止web服務。   
nginx -s quit       #平穩關閉Nginx,保存相關信息,有安排的結束web服務。        
nginx -s reload     #因改變了Nginx相關配置,需要重新加載配置而重載。            
nginx -s reopen     #重新打開日誌文件。                                         
nginx -c filename   #爲 Nginx 指定一個配置文件,來代替缺省的。                   
nginx -t            #不運行,而僅僅測試配置文件。nginx 將檢查配置文件的語法的正確性,並嘗試打開配置文件中所引用到的文件。                                        
nginx -v            #顯示 nginx 的版本。                                        
nginx -V            #顯示 nginx 的版本,編譯器版本和配置參數。

注意運行這些命令要在nginx.exe所在的路徑下。

2 nginx配置

2.1 一個簡單例子

場景:我們現在在本地啓動了兩個web項目,訪問地址分別爲“127.0.0.8081”和“127.0.0.8081”,要實現代理/反向代理,負載均衡可以像下面這樣配置。

下面是一個默認初始的nginx.conf文件,其他都沒變,添加的是藍色框中的代碼,該文件的關鍵部分,如下圖:

注意:

兩個藍色框中都有myWebs,mywebs是後臺服務器組的名稱,這兩個地方一定要一樣。

在上面例子中,如果你的web項目登錄路徑爲:127.0.0.1:8080/webAppName 那麼nginx配置啓動後,應該訪問 localhost:80/webAppName

2.2 語句含義


#user  nobody;        #定義 Nginx 運行的用戶和用戶組,默認由 nobody 賬號運行, windows 下面可以註釋掉。
worker_processes  1;  #nginx進程數,建議設置爲等於CPU總核心數。可以和worker_cpu_affinity配合

#全局錯誤日誌定義類型,[ debug | info | notice | warn | error | crit ]
error_log  logs/error.log;
error_log  logs/error.log  notice;
error_log  logs/error.log  info;

#pid        logs/nginx.pid;  #進程文件,window下可以註釋掉


events {
accept_mutex on;   #設置網路連接序列化,防止驚羣現象發生,默認爲on
    multi_accept on;  #設置一個進程是否同時接受多個網絡連接,默認爲off
    #use epoll;      #事件驅動模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport
    worker_connections  1024; # 單個進程最大連接數(最大連接數=連接數*進程數)該值受系統進程最大打開文件數限制,需要使用命令ulimit -n 查看當前設置
}


http {
    include       mime.types;  		    #文件擴展名與文件類型映射表
    default_type  application/octet-stream;    #默認文件類型,默認爲text/plain

    #定義虛擬主機日誌的格式
    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指令指定nginx是否調用sendfile函數來輸出文件,對於普通應用設爲 on,如果用來進行下載等應用磁盤IO重負載應用,可設置爲off,以平衡磁盤與網絡I/O處理速度,降低系統的負載。注意:如果圖片顯示不正常把這個改成off。
    sendfile        on;
	
	#autoindex on; #開啓目錄列表訪問,合適下載服務器,默認關閉。
    
	#防止網絡阻塞
	#tcp_nopush     on;

	#長連接超時時間,單位是秒,默認爲0
    #keepalive_timeout  0;
    keepalive_timeout  65;  

	#開啓gzip壓縮輸出
    #gzip  on;
	
	#被代理的後臺服務器列表
	upstream myWeb {
		 server 127.0.0.1:8081 weight=1;
		 server 127.0.0.1:9081 weight=1;
		 ip_hash;  #ip_hash 模式,解決session不能共享問題
    }

    server {
        listen       2041;   # 監聽端口
        server_name  localhost;  #域名可以有多個,用空格隔開

        #charset koi8-r;
        charset utf-8;   #字符編碼設置
        #access_log  logs/host.access.log  main;   #定義本虛擬主機的訪問日誌

        location / {
	#   root   html;   					#一個基本路徑
        #   index  index.html index.htm;	# 在上面的基本路徑下找該文件,若是靜態文件(html)則展示;若是動態文件(jsp)在下載
	    proxy_pass http://myWeb;        # 代理的後臺服務器列表
			
	    proxy_set_header Host $host:$server_port;
	    proxy_set_header X-Real-IP $remote_addr;   # 獲取用戶的真實 IP 地址
			
	    #後端的Web服務器可以通過 X-Forwarded-For 獲取用戶真實IP,多個 nginx 反代的情況下,例如 CDN。參見:http://gong1208.iteye.com/blog/1559835 和 http://bbs.linuxtone.org/thread-9050-1-1.html
	    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;   
			
	    proxy_connect_timeout       10000;   
	    proxy_read_timeout          10000;
	    proxy_send_timeout          10000;

        }
		
	#設定查看Nginx狀態的地址
        location /NginxStatus {
            stub_status           on;
            access_log            on;
            auth_basic            "NginxStatus";
            auth_basic_user_file  conf/htpasswd;
        }
		

        #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;
    #    }
    #}

}

2.3 重要模塊

2.3.1 負載均衡

Nginx負載均衡是通過upstream模塊來實現的,內置實現了三種負載策略,配置還是比較簡單的。官網負載均衡配置說明如下圖:

官網地址:http://nginx.org/en/docs/http/load_balancing.html

我們接下來一個個看。

2.3.1.1輪循(默認)

顧名思義,後臺服務器組的各個服務器會一個接着一個,輪流去處理請求。從整體上來看,每臺服務器處理的請求數是差不多的。

upstream 塊是配置負載均衡的,webs1是後臺服務器組名稱;

location 塊是配置代理/反向代理的(具體見下一個模塊)

2.3.1.2.最少連接

那個服務器處理的請求(被連接的)的次數最少,就那個服務器去處理當前這個請求

 

2.3.1.3.會話持久性

解決session共享問題。適用場景,當你的後臺服務器有多個,涉及登錄,session驗證問題。一個客戶端會持續訪問一個固定的服務器。

 

2.3.1.4.一些其他設置

(1) weight

默認爲1,將請求平均分配給每臺server,例如:

upstream webs1 {

        server 192.168.0.101:8081 weight=2;

        server 192.168.0.102:8082 weight=2;

        server 192.168.0.103:8083 weight=1;

}

如果有5各請求,那麼這3臺服務器從上到下,分別處理請求個數爲2、2、1。

(2) max_fails fail_timeout

max_fails默認爲1。某臺Server允許請求失敗的次數,超過最大次數後,在fail_timeout時間內,新的請求將不會分配給這臺機器。如果設置爲0,Nginx會將這臺Server置爲永久無效狀態,然後將請求發給定義了proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream, and memcached_next_upstream指令來處理這次錯誤的請求。

fail_timeout默認爲10秒。某臺Server達到max_fails次失敗請求後,在fail_timeout期間內,nginx會認爲這臺Server暫時不可用,不會將請求分配給它

max_fails和fail_timeout的使用,如下:

upstream webs1 {

        server 192.168.0.101:8081 max_fails=3 fail_timeout=15;

        server 192.168.0.102:8082 max_fails=3 fail_timeout=15;

        server 192.168.0.103:8083 max_fails=3 fail_timeout=15;

}

即,在15秒內,如果某臺服務器連續處理請求失敗了3次,則這臺服務器判定爲宕機,請求將不會讓這臺服務器處理。

 

(3)backup

備份技機,其他服務器宕機後,纔會這臺備份機(服務器)。

upstream webs1 {
        server 192.168.0.101:8081 max_fails=3 fail_timeout=15;
	server 192.168.0.102:8082 max_fails=3 fail_timeout=15;
	server 192.168.0.103:8083 backup;
 }

當前兩臺服務器宕機後,請求才會發到第三臺服務器上。

 

(4)down

標識某臺服務器不可用,請求不會發到這臺服務器。

upstream webs1 {
        server 192.168.0.101:8081 max_fails=3 fail_timeout=15;
	server 192.168.0.102:8082 down;
	server 192.168.0.103:8083 backup;
}

 

(5)max_conns

限制分配給某臺Server處理的最大連接數量,超過這個數量,將不會分配新的連接給它。默認爲0,表示不限制。注意:1.5.9之後的版本纔有這個配置。

upstream webs1 {
        server 192.168.0.101:8081;
	server 192.168.0.102:8082;
	server 192.168.0.103:8083 max_oount=10;
}

 

(6)resolve

將server指令配置的域名,指定域名解析服務器。需要在http模塊下配置resolver指令,指定域名解析服務。

具體見官方文檔:http://nginx.org/en/docs/http/ngx_http_upstream_module.html#resolver

2.3.2 代理/反向代理

一般是在location塊中配置的。

2.3.1.1 默認配置

我們先來看看,默認nginx的默認配置,爲什麼啓動nginx後,在瀏覽器中輸入域名(一般是localhost),會出現nginx的歡迎頁面呢?

下面是nginx默認的初始nginx.conf文件的部分配置,其中紅框中是location塊的配置。

root  html;   

html是一個基本路徑(相對路徑或者絕對路徑)。

index  index.html  index.htm;

當在瀏覽器中訪問localhost:80或者localhost(端口默認爲80)時,是在root配置的基本路徑下找index.html 或者 index.htm文件並且響應到頁面展示,如果不能展示則去下載該文件。

我們去nginx文件下找html文件下,看能不能找到index.html或者index.htm文件,找到了,如下圖:

我們雙擊index.html,響應頁面正好就是我們在剛開始啓動nginx時,瀏覽器中訪問localhost時響應的頁面,如下圖:

 

2.3.1.2 與upstream配合使用

我們再次回過頭來看2.1中的那一個簡單的例子。

proxy_pass  http://myWebs

這個location塊接收(攔截)的請求(不是localhost:80請求)會去轉發給myWebs這個服務器組裏面的一臺服務器去處理。

兩個藍色框中用到的服務器組名稱一定要保持一致(比如,都是myWebs)。

2.3.1.3 其他

loction塊的配置還有很多,可以去https://segmentfault.com/a/1190000013781162 查看該文章的“location如何匹配“模塊。

3 可能遇到的問題

3.1 nginx配置後,只有一個頁面(首頁)能正常訪問,其他頁面全加載不出來

3.1.1描述

當配置完ginx啓動後,只有一個頁面可以正常訪問(一般情況下是登錄頁,只能登錄進系統),接着點擊其他頁面無反應,打開F2開發者模式,查看請求頭,請求路徑是:”

http://localhost:80/setPassword.html,裏面的localhost是你nginx配置的域名,80端口是nginx配置的監聽端口。

3.1.2 解決

當請求到代理服務器(一般是你的後臺服務器,會有多個),不能獲取到真實的後臺服務器ip,所以就用你配置的域名去請求了。

給location 塊裏面添加下面代碼:

proxy_set_header Host $host:$server_port;

proxy_set_header X-Real-IP $remote_addr;   # 獲取用戶的真實 IP 地址

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 

如下圖:

3.2 Nginx報錯"no live upstreams while connecting to upstream",錯誤碼502

 

3.2.1 描述

前提是你的後臺服務器有兩臺(可能你的情況是多臺),nginx和web項目部署在同一臺服務器上。當你關閉和nginx部署在同一臺服務器上的web項目時(人爲造成一臺服務器故障),再次請求時發現響應頁面如下:

 

打開nginx的logserror.log日誌,查看報錯信息爲“no live upstreams while connecting to upstream”;

頁面上F12查看報錯“502,bad gateway!“

3.2.2 解決

當你嘗試了網上的多種解決方案無果後,試試在 nginx和web項目都部署了那臺服務器A訪問其他服務器B上的web項目,若還是訪問失敗。那麼恭喜你,問題就要解決了。

你的請求被服務器B的防火牆攔截了,要麼關掉B服務器的防火牆,要麼設置服務器B防火牆的出入站規則(開放請求所用的端口)

3.3 用nginx進行負載均衡時,web項目的session共享問題

3.3.1 描述

當你的web項目技術很簡單,登錄的session沒有存數據庫,也沒有存redis。在部署上線時,web項目有多個節點(web項目在多臺服務器上啓動了)這時用nginx做代理/反向代理,負載均衡時怎麼解決登錄一臺服務器時session共享給所以服務器呢?

最直觀的響應就是,當你配置好nginx啓動後,發出請求可能會報空指針異常。

3.3.2 解決

  1. 方案一,修改web項目代碼,把session入庫(reids或關係型數據庫),這樣成本大不採取;
  2. 方案二,註釋驗證session的攔截器,任何人不登錄都可以訪問該網站了,出於安全性的考慮,不可取;
  3. 方案三,負載均衡時,採用ip_hash策略,固定的客戶端訪問固定的服務端,完美解決session共享問題;

3.4 服務器上配置好nginx後,用兩臺電腦訪問,總是命中後臺某一個服務器

3.4.1 描述

當你用配置好nginx,負載均衡部分採用的ip_hash策略。用局域網內的兩臺服務器訪問服務器(服務器和你不是同一個局域網),發現這兩臺電腦發出請求命中的後臺服務器竟然是一臺(往往是upstream節點裏面配置的第一臺)。這負載均衡也沒生效啊,是什麼原因呢?

當服務器部署的網和你的客戶端訪問的網是同一個網時,一般出現上述問題。

3.4.2 解決

事實上這是正常現象,不需要解決。

因爲,在nginx使用ip_hash這種策略時,內部是使用ip的前三段去做關鍵字進行hash處理的。當你用同一局域網當的兩臺電腦(這兩臺電腦ip的前三段是一樣的)去訪問時就會始終命中後臺的某一臺服務器。

當你一臺電腦連你的局域網,一臺連手機熱點,再次訪問服務器時,就會發行請求命中到了不同的服務器上。

3.5 要對某些代理做驗證

3.5.1 描述

現在有個location節點需要做驗證,輸入賬戶密碼才能訪問,該節點如下:

根據上面配置可以看到nginx監聽端口:80,域名:localhost。訪問/NginxStatus時需要驗證,驗證文件是nginx-1.16.1/conf/htpasswd。

3.5.2 解決

現在我們在conf文件夾下新建一個htpasswd文件,不要後綴名(可以先新建文本文件,再刪掉後綴名)。文件內容如下:

可以發現用戶名是cdd,密碼是123456。配置好後,我們重啓nginx,在瀏覽器中輸入localhost:80/NginxStatus,回車,響應頁面如下要輸入賬戶和密碼。

我們用戶名輸入cdd,密碼輸入:123456,點擊登錄,響應頁面如下:

4 參考資料

nginx中文文檔:

https://www.nginx.cn/doc/index.html

nginx局域網中使用ip_hash策略,總是命中後臺某一臺服務器:

https://blog.csdn.net/sd4493091/article/details/54894479?utm_source=itdadao&utm_medium=referral

https://www.linuxidc.com/Linux/2014-02/96868.htm

linux環境下安裝nginx:https://jingyan.baidu.com/article/e3c78d648516243c4c85f5c2.html

nginx的使用及配置:https://blog.csdn.net/finnson/article/details/82461600

前端nginx使用札記https://segmentfault.com/a/1190000013781162

nginx負載均衡配置:https://blog.csdn.net/xyang81/article/details/51702900

nginx語句含義:https://www.cnblogs.com/knowledgesea/p/5175711.html

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