Nginx-正反向代理及負載均衡


正/反向代理

代理的作用是將流量分配

代理的方式

  • 正向代理:找完正向代理之后,還需要找服務器(無法直接訪問到目標服務器)
    • 應用:VPN

img

  • 反向代理:只需要找反向代理,不需要找服務器
    • 應用:負載均衡

img

Nginx代理服務支持的協議

👉nginx官網

模塊 代理語言
ngx_http_uwsgi_module Python
ngx_http_fastcgi_module PHP
ngx_http_scgi_module Java
ngx_http_v2_module Golang
ngx_http_proxy_module HTTP

代理實戰

Lb01虛擬機代理Web01

部署web01

搭建馬里奧小游戲

[root@web01 conf.d]# vim Mario.conf 
server{
    listen 80;
    server_name 192.168.15.7;
    location / {
	root /opt/Super_Mario;
        index index.html;    
    }
    location ~ /images {
        root /opt/image;
    }
}

部署Lb01

  • Lb01部署Nginx
# 下載Nginx源代碼包
[root@lb01 ~]# wget https://nginx.org/download/nginx-1.20.2.tar.gz

# 解壓
[root@lb01 ~]# tar -xf nginx-1.20.2.tar.gz

# 進入源代碼目錄
[root@lb01 ~]# cd nginx-1.20.2

# 安裝依賴包
[root@lb01 nginx-1.20.2]# yum install openssl openssl-devel zlib zlib-devel -y

# 設置編譯參數
[root@lb01 nginx-1.20.2]# ./configure  --with-http_gzip_static_module    --with-stream     --with-http_ssl_module

# 編譯
[root@lb01 nginx-1.20.2]# make 

# 安裝
[root@lb01 nginx-1.20.2]# make install 

# 優化
[root@lb01 nginx]# mkdir /etc/nginx
[root@lb01 nginx]# mv /usr/local/nginx/conf/* /etc/nginx/
[root@lb01 nginx]# mkdir /etc/nginx/conf.d

# 修改配置文件(拷貝以下web01的),統一內容
[root@web01 ~]# cat /etc/nginx/nginx.conf
    # 拷貝到lb01配置文件中
[root@lb01 nginx]# vim /etc/nginx/nginx.conf


[root@lb01 nginx]# groupadd www -g 666
[root@lb01 nginx]# useradd www -u 666 -g 666 -M -r -s /sbin/nologin

[root@lb01 nginx]# vim /usr/lib/systemd/system/nginx.service
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/sh -c "/bin/kill -s HUP $(/bin/cat /var/run/nginx.pid)"
ExecStop=/bin/sh -c "/bin/kill -s TERM $(/bin/cat /var/run/nginx.pid)"

[Install]
WantedBy=multi-user.target

[root@lb01 sbin]# ln -s /etc/nginx/nginx.conf /usr/local/nginx/conf/nginx.conf
[root@lb01 sbin]# mv /usr/local/nginx/sbin/nginx /usr/sbin/
# 重載 
[root@lb01 sbin]# systemctl daemon-reload
[root@lb01 sbin]# mkdir /var/log/nginx
[root@lb01 sbin]# systemctl start nginx 
# 查看模塊
[root@lb01 nginx]# nginx -V 
  • 部署反向代理
[root@lb01 conf.d]# vim /etc/nginx/conf.d/game.conf 
server {
    listen 80;
    server_name _;
    location / {
        proxy_pass http://172.16.1.7:80;
    }
}
# 測試
真機訪問192.168.15.5(lb01)

image


Nginx代理常用參數

添加發往后端服務器的請求頭信息

通過tail -f /var/log/nginx/access.log監控日志,發現客戶端ip是lb01的,通過以下三個參數修改就能記錄真實的客戶端ip

Syntax:    proxy_set_header field value;
Default:    proxy_set_header Host $http_host;
            proxy_set_header Connection close;
Context:    http, server, location
 
# 用戶請求的時候HOST的值是linux.proxy.com, 那么代理服務會像后端傳遞請求的還是linux.proxy.com
proxy_set_header Host $http_host;
# 將$remote_addr的值放進變量X-Real-IP中,$remote_addr的值為客戶端的ip
proxy_set_header X-Real-IP $remote_addr;
# 客戶端通過代理服務訪問后端服務, 后端服務通過該變量會記錄真實客戶端地址
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 添加參數
[root@lb01 nginx]# vim /etc/nginx/conf.d/game.conf
server {
    listen 80;
    server_name _;
    location / {
        proxy_pass http://172.16.1.7:80;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
[root@lb01 nginx]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@lb01 nginx]# systemctl restart nginx 

再次監控web01,發現真實ip為”xff”: "192.168.15.1"

代理到后端的TCP連接、響應、返回等超時時間

#nginx代理與后端服務器連接超時時間(代理連接超時)
Syntax: proxy_connect_timeout time;
Default: proxy_connect_timeout 60s;
Context: http, server, location
 
#nginx代理等待后端服務器的響應時間
Syntax:    proxy_read_timeout time;
Default:    proxy_read_timeout 60s;
Context:    http, server, location
 
#后端服務器數據回傳給nginx代理超時時間
Syntax: proxy_send_timeout time;
Default: proxy_send_timeout 60s;
Context: http, server, location


# 添加以下參數
proxy_connect_timeout 1s;   # 連接時間
proxy_read_timeout 3s;     # 響應時間
proxy_send_timeout 3s;     # 回傳代理時間

[root@lb01 nginx]# cat /etc/nginx/conf.d/game.conf
server {
    listen 80;
    server_name _;
    location / {
        proxy_pass http://172.16.1.7:80;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # -----------------------------------------------------
        proxy_connect_timeout 1s;
        proxy_read_timeout 3s;
        proxy_send_timeout 3s;
    }
}

proxy_buffer代理緩沖區

代理緩沖區的存在增快了訪問速度

#nignx會把后端返回的內容先放到緩沖區當中,然后再返回給客戶端,邊收邊傳, 不是全部接收完再傳給客戶端
Syntax: proxy_buffering on | off;
Default: proxy_buffering on;  
Context: http, server, location
 
#設置nginx代理保存用戶頭信息的緩沖區大小
Syntax: proxy_buffer_size size;
Default: proxy_buffer_size 4k|8k;
Context: http, server, location
 
#proxy_buffers 緩沖區
Syntax: proxy_buffers number size;
Default: proxy_buffers 8 4k|8k;
Context: http, server, location

proxy_buffering on; 
proxy_buffer_size 8k;
proxy_buffers 8 8k;
# 添加參數
proxy_buffering on;  # 打開緩沖區
proxy_buffer_size 8k;   # 緩沖區大小,設置為8kb
proxy_buffers 8 8k;   # 8個緩沖區,每個緩沖區8kb


[root@lb01 nginx]# cat /etc/nginx/conf.d/game.conf
server {
    listen 80;
    server_name _;
    location / {
        proxy_pass http://172.16.1.7:80;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # -----------------------------------------------------
        proxy_connect_timeout 1s;
        proxy_read_timeout 3s;
        proxy_send_timeout 3s;
        # ----------------------------------------------------
        proxy_buffering on;
        proxy_buffer_size 8k;
        proxy_buffers 8 8k;
    }
}

配置代理優化文件

因為上面參數在配置的時候是不需要修改的,通過寫入到文件內來優化

[root@lb01 ~]# cd /etc/nginx/
[root@lb01 ~]# vim /etc/nginx/proxy_params 
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 10s;
proxy_read_timeout 10s;
proxy_send_timeout 10s;
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 8k;

# 編輯配置文件,通過添加外部配置文件-include,就不需要寫上述的參數了
[root@lb01 conf.d]# vim game.conf 
server {
    listen 80;
    server_name _;
    location / {
        proxy_pass http://172.16.1.7:80;
        include /etc/nginx/proxy_params;
    }
}

# 測試
通過監控進程來查看真實ip是否為本機訪問的真實ip即可
tail -f /var/log/nginx/access.log

負載均衡

為什么要用負載均衡?

可以拓展代理,使用負載均衡可以代理多個主機,

負載均衡的架構

通過代理將流量按照一定的比例,轉發到后端。

負載均衡的實現

連接池

將后端服務打包成一個IP連接池。

1、反向代理格式
server {
   	listen 80;
   	server_name _;
   	location / {
        proxy_pass http://[連接池];
   	}
}

2、IP連接池格式
upstream [連接池名稱] {
    server [ip]:[port];
    server [ip]:[port];
    server [ip]:[port];
}

實現步驟

# 搭建
web02和web03 用nginx搭建馬里奧小游戲
1、上傳文件到/opt/目錄下
[root@web01 conf.d]# scp Super_Mario.tar.gz 172.16.1.8:/opt/
[root@web01 conf.d]# scp Super_Mario.tar.gz 172.16.1.9:/opt/
2、下載nginx : yum install nginx
3、編輯配置文件:Mario.conf
[root@web01 conf.d]# scp Mario.conf 172.16.1.8:/etc/nginx/conf.d/
[root@web01 conf.d]# scp Mario.conf 172.16.1.9:/etc/nginx/conf.d/
4、修改配置文件和web01統一
[root@web01 conf.d]# scp /etc/nginx/nginx.conf 172.16.1.8:/etc/nginx/nginx.conf 
[root@web01 conf.d]# scp /etc/nginx/nginx.conf 172.16.1.9:/etc/nginx/nginx.conf 
5、web02和web03測試配置文件和重啟服務
 nginx -t -c /etc/nginx/nginx.conf
 systemctl restart nginx 

# lb01實現負載均衡
6、創建連接池
[root@lb01 conf.d]# vim /etc/nginx/conf.d/game.conf
upstream supermarie {
    server 172.16.1.7:80;
    server 172.16.1.8:80;
    server 172.16.1.9:80;
}

server {
    listen 80;
    server_name _;
    location / {
        proxy_pass http://supermarie;
        include /etc/nginx/proxy_params;
    }
}
[root@lb01 conf.d]# nginx -t
[root@lb01 conf.d]# systemctl restart nginx 
# 測試真機訪問lb01 ip

image

這樣的負載均衡訪問,訪問流量是平均分配的,如何實現負載均衡流量比例不一樣呢?👉負載均衡比例

負載均衡的比例

流量比例示例如下

輪詢

# 通過web01字符顯示示例
[root@web01 Super_Mario]# echo Web01 > web.html
[root@web01 Super_Mario]# echo Web02 > web.html
[root@web01 Super_Mario]# echo Web03 > web.html
# 默認情況下,Nginx負載均衡的輪詢狀態。
upstream supermarie {
    server 172.16.1.7:80;
    server 172.16.1.8:80;
    server 172.16.1.9:80;
}

權重

# Nginx中的權重0-100,數字越大,權重越高。
upstream supermarie {
    server 172.16.1.7:80 weight=9;
    server 172.16.1.8:80 weight=5;
    server 172.16.1.9:80 weight=1;
}
# 這樣web01獲得流量分配的幾率就大

ip_hash

# 每一個IP固定訪問某一個后端。
upstream supermarie {
    server 172.16.1.7:80;
    server 172.16.1.8:80;
    server 172.16.1.9:80;
    ip_hash;
}

# 這樣就固定訪問web01服務器ip,172.16.1.7

負載均衡后端狀態

狀態 概述
down 當前的server暫時不參與負載均衡
backup 預留的備份服務器
max_fails 允許請求失敗的次數
fail_timeout 經過max_fails失敗后, 服務暫停時間

down

# 暫時不分配流量
upstream supermarie {
    server 172.16.1.7:80 down;
    server 172.16.1.8:80;
    server 172.16.1.9:80;
}

server {
    listen 80;
    server_name _;
    location / {
        proxy_pass http://supermarie;
        include /etc/nginx/proxy_params;
    }
}
# 這樣172.16.1.7這個服務器暫時就不會分配流量,不參與負載均衡

backup

# 只有當所有的機器全部宕機,才能啟動。
upstream supermarie {
    server 172.16.1.7:80 backup;
    server 172.16.1.8:80;
    server 172.16.1.9:80;
}

server {
    listen 80;
    server_name _;
    location / {
        proxy_pass http://supermarie;
        include /etc/nginx/proxy_params;
    }
}

# 這樣只有web02和web03宕機了才會訪問172.16.1.7服務器

max_fails、fail_timeout

max_fails、fail_timeout一起使用

max_fails:允許請求失敗的次數
fail_timeout:經過max_fails失敗后, 服務暫停時間
# proxy_next_upstream 后端錯誤標識

[root@lb01 ~]# cat /etc/nginx/conf.d/game.conf 
upstream supermarie {
    server 172.16.1.7:80 max_fails=3 fail_timeout=3s;
    server 172.16.1.8:80 max_fails=3 fail_timeout=3s;
    server 172.16.1.9:80 max_fails=3 fail_timeout=3s;
}

server {
    listen 80;
    server_name _;
    location / {
        proxy_pass http://supermarie;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_404; 
        include /etc/nginx/proxy_params;
    }
}
# 后端出現錯誤,會自動干掉服務,不會去訪問
proxy_next_upstream監控的錯誤類型
# proxy_next_upstream可以指定的錯誤類型如下👇:

error             # 與服務器建立連接,向其傳遞請求或讀取響應頭時發生錯誤;
timeout           # 在與服務器建立連接,向其傳遞請求或讀取響應頭時發生超時;
invalid_header    # 服務器返回空的或無效的響應;
http_500          # 服務器返回代碼為500的響應;
http_502          # 服務器返回代碼為502的響應;
http_503          # 服務器返回代碼為503的響應;
http_504          # 服務器返回代碼504的響應;
http_403          # 服務器返回代碼為403的響應;
http_404          # 服務器返回代碼為404的響應;
http_429          # 服務器返回代碼為429的響應(1.11.13);
non_idempotent    # 通常,請求與 非冪等 方法(POST,LOCK,PATCH)不傳遞到請求是否已被發送到上游服務器(1.9.13)的下一個服務器; 啟用此選項顯式允許重試此類請求;
off               # 禁用將請求傳遞給下一個服務器。

負載均衡部署BBS

部署后端服務

部署Python

web01、web02、web03部署,統一步驟

1、創建用戶
[root@web01 opt]# groupadd django -g 888
[root@web01 opt]# useradd django -u 888 -g 888 -r -M -s /bin/sh

2、安裝依賴軟件
[root@web01 opt]# yum install python3 libxml* python-devel gcc* pcre-devel openssl-devel python3-devel -y

3、上傳文件
[root@web01 ~]# scp bbs.zip 172.16.1.8:/opt/
[root@web01 ~]# scp bbs.zip 172.16.1.9:/opt/
部署Django和uwsgi
4、安裝Django和uwsgi
[root@web01 opt]# pip3 install django==1.11
[root@web01 opt]# pip3 install uwsgi
[root@web01 opt]# pip3 install pymysql

5、創建項目
[root@web01 opt]# unzip bbs.zip 
[root@web03 bbs]# pwd
/opt/bbs
[root@web03 bbs]# vim bbs/settings.py 
ALLOWED_HOSTS = ['*']
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'bbs',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '172.16.1.61',
        'PORT': 3306,
        'CHARSET': 'utf8'
    }
}

# 啟動測試
[root@web01 bbs]# python3 manage.py runserver 0.0.0.0:8000
# 注意數據庫遠程連接必須開啟
配置並啟動uwsgi
6、編輯項目配置文件
[root@web01 bbs]# vim /opt/bbs/myweb_uwsgi.ini 
[uwsgi]
# 端口號
socket            = :8000
# 指定項目的目錄
chdir           = /opt/bbs
# wsgi文件路徑
wsgi-file       = bbs/wsgi.py
# 模塊wsgi路徑
module          = bbs.wsgi
# 是否開啟master進程
master          = true
# 工作進程的最大數目
processes       = 4
# 結束后是否清理文件
vacuum          = true

7、啟動uwsgi(在bbs目錄測試)
[root@web01 bbs]# uwsgi -d --ini myweb_uwsgi.ini --uid 666

-d 	  : 以守護進程方式運行
--ini : 指定配置文件路徑
--uid : 指定uid

TCP 服務

8、編輯Nginx配置文件
[root@web01 ~]# vim /etc/nginx/conf.d/python.conf 
server {
    listen 80;
    server_name py.test.com;
    location / { 
        include uwsgi_params;
        uwsgi_pass 127.0.0.1:8000;
        uwsgi_read_timeout 2;
        uwsgi_param UWSGI_SCRIPT bbs.wsgi;
        uwsgi_param UWSGI_CHDIR /opt/bbs;
        index  index.html index.htm;
        client_max_body_size 35m;
    }
}

9、測試且重啟Nginx配置
nginx -t
systemctl restart nginx

部署負載均衡

[root@lb01 conf.d]# vim python.conf 
upstream bbs {
    server 172.16.1.7:80 max_fails=3 fail_timeout=3s;
    server 172.16.1.8:80 max_fails=3 fail_timeout=3s;
    server 172.16.1.9:80 max_fails=3 fail_timeout=3s;
}

server {
    listen 80;
    server_name py.test.com;
    location / {
        proxy_pass http://bbs;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_404; 
        include /etc/nginx/proxy_params;
    }
}

[root@lb01 conf.d]# nginx -t
[root@lb01 conf.d]# systemctl restart nginx 

# 域名解析
windows下hosts文件
# 注意連接池的名稱不能相同,和其他的負載均衡連接池區分

# 真機測試是否成功

image


補充

頁面出現502問題原因


免責聲明!

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



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