Nginx-正反向代理及负载均衡
目录
- 正/反向代理
- 代理的方式
- Nginx代理服务支持的协议
- 代理实战
- 部署web01
- 部署Lb01
- Nginx代理常用参数
- 添加发往后端服务器的请求头信息
- 代理到后端的TCP连接、响应、返回等超时时间
- proxy_buffer代理缓冲区
- 配置代理优化文件
- 负载均衡
- 负载均衡的架构
- 负载均衡的实现
- 连接池
- 实现步骤
- 负载均衡的比例
- 轮询
- 权重
- ip_hash
- 负载均衡后端状态
- down
- backup
- max_fails、fail_timeout
- proxy_next_upstream监控的错误类型
- 负载均衡部署BBS
- 部署后端服务
- 部署Python
- 部署Django和uwsgi
- 配置并启动uwsgi
- 部署负载均衡
- 补充
- 页面出现502问题原因
正/反向代理
代理的作用是将流量分配
代理的方式
- 正向代理:找完正向代理之后,还需要找服务器(无法直接访问到目标服务器)
- 应用:VPN
- 反向代理:只需要找反向代理,不需要找服务器
- 应用:负载均衡
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)
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
这样的负载均衡访问,访问流量是平均分配的,如何实现负载均衡流量比例不一样呢?👉负载均衡比例
负载均衡的比例#
流量比例示例如下
轮询#
# 通过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文件 # 注意连接池的名称不能相同,和其他的负载均衡连接池区分 # 真机测试是否成功
补充
页面出现502问题原因#
- 个人在配置uwsgi配置出问题,杀掉uwsgi进程,重启启动
- 可以参考博文:https://my.oschina.net/junn/blog/147923