nginx反向代理及负载均衡

华子目录

nginx反向代理功能

  • 反向代理reverse proxy,指的是代理外网用户的请求内部的指定的服务器,并将数据返回给用户一种方式,这是用的比较多一种方式
  • Nginx除了可以在企业提供高性能web服务之外,另外还可以将nginx本身不具备的请求通过某种预定义的协议转发至其它服务器处理不同的协议就是Nginx服务器其他服务器进行通信一种规范,主要在不同的场景使用以下模块实现不同的功能:
  • ngx_http_proxy_module 将客户端的请求以http协议转发至指定服务器进行处理
  • ngx_http_upstream_module 用于定义为proxy_pass,fastcgi_pass,uwsgi_pass等指令引用的后端服务器分组
  • ngx_stream_proxy_module 将客户端的请求以tcp协议转发至指定服务器处理
  • ngx_http_fastcgi_module 将客户端对php的请求以fastcgi协议转发至指定服务器助理
  • ngx_http_uwsgi_module 将客户端对Python的请求以uwsgi协议转发至指定服务器处理

逻辑调用关系:

访问逻辑图:

  • 同构代理用户不需要其他程序参与直接通过http协议或者tcp协议访问后端服务器
  • 异构代理用户访问资源时需要经过处理后才能返回,比如php,python等等,这种访问资源需要经过处理才能被访问

http反向代理

官方文档:https://nginx.org/en/docs/http/ngx_http_proxy_module.html

反向代理配置参数

  • proxy_pass 用来设置将客户端请求转发给的后端服务器的主机,
  • 可以是主机名:端口IP地址:端口
  • 也可以代理预先设置主机群组,需要模块ngx_http_upstream_module支持
  • proxy_hide_header field 用于nginx作为反向代理的时候,在返回给客户端http响应时,隐藏后端服务器相应头部的信息,可以设置在http,server或location块
bash 复制代码
#示例: 隐藏后端服务器ETag首部字段
location /web {
	index index.html;
	proxy_pass http://10.0.0.18:8080/;
	proxy_hide_header ETag;
}
  • proxy_pass_header field 透传,默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel等参数,如果要传递的话则要使用proxy_pass_header field声明将后端服务器返回的值传递给客户端
  • field 首部字段大小不敏感
bash 复制代码
#示例:透传后端服务器的Server和Date首部给客户端,同时不再响应报中显示前端服务器的Server字段
proxy_pass_header Server;
proxy_pass_header Date;
  • proxy_pass_request_body on | off 是否向后端服务器发送HTTP实体部分,可以设置在http,server或location块,默认即为开启
  • proxy_pass_request_headers on | off 是否将客户端的请求头部转发给后端服务器,可以设置在http,server或location块,默认即为开启
  • proxy_set_header 可更改或添加客户端的请求头部信息内容并转发至后端服务器,比如在后端服务器想要获取客户端的真实IP的时候,就要更改每一个报文的头部
bash 复制代码
#示例:
location ~ /web {
	proxy_pass http://172.25.254.20:80;
	proxy_hide_header ETag;
	proxy_pass_header Server;
	proxy_pass_request_body on;
	proxy_pass_request_headers on;
	proxy_set_header X-Forwarded-For $remote_addr;
}
  • proxy_connect_timeout time 配置nginx服务器与后端服务器尝试建立连接的超时时间,默认为60秒
bash 复制代码
#用法如下:proxy_connect_timeout 60s;
#60s为自定义nginx与后端服务器建立连接的超时时间,超时会返回客户端504响应码
  • proxy_read_timeout time 配置nginx服务器向后端服务器或服务器组发起read请求后,等待的超时时间,默认60s
  • proxy_send_timeout time 配置nginx项后端服务器或服务器组发起write请求后,等待的超时 时间,默认60s
  • proxy_http_version 1.0 用于设置nginx提供代理服务的HTTP协议的版本,默认http 1.0
  • proxy_ignore_client_abort off 当客户端网络中断请求时,nginx服务器中断其对后端服务器的请求。即如果此项设置为on开启,则服务器、会忽略客户端中断并一直等着代理服务执行返回,如果设置为off,则客户端中断后Nginx也会中断客户端请求并立即记录499日志,默认为off

proxy_pass的注意事项

bash 复制代码
location /web {
	index index.html;
	proxy_pass  http://172.25.254.30:8080;
}
#8080后面无uri,即无/符号,会将location后面的url加到proxy_pass指定的url后面,此行为类似于root
#proxy_pass指定的uri不带斜线将访问/web下的内容
  • 如果location定义其uri时使用了正则表达式模式(包括~,~*,但不包括^~),则proxy_pass之后必须不能使用uri。即不能/用户请求时传递的uri直接附加后端服务器之后
bash 复制代码
location /web {
	index index.html;
	proxy_pass  http://172.25.254.30:8080/;
}
#8080后面有uri,即/符号,此行为类似于alias
#proxy_pass指定的uri带斜线等于访问http://172.25.254.30:8080/index.html
  • location中的proxy_pass只能有一个,不能有多个,否则会报错

案例反向代理单台后端服务器

  • nginx服务器172.25.254.100 www.huazi.org
  • web1服务器172.25.254.10
bash 复制代码
[root@web1 ~]# yum install httpd -y
[root@web1 ~]# echo 172.25.254.10 > /var/www/html/index.html
[root@web1 ~]# systemctl start httpd
bash 复制代码
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
    listen 80;
    server_name www.huazi.org;
    location / {
        proxy_pass http://172.25.254.10:80;
    }
}

[root@nginx-node1 ~]# nginx -s reload

测试:当访问www.huazi.org时,nginx会将请求代理到web1

案例:反向代理实现动静分离

  • nginx服务器172.25.254.100 www.huazi.org
  • web1服务器172.25.254.10
  • web2服务器172.25.254.20
bash 复制代码
[root@web1 ~]# yum install php -y
[root@web1 ~]# vim /var/www/html/index.php
<?php
    phpinfo();
?>

[root@web1 ~]# systemctl restart httpd
bash 复制代码
[root@web2 ~]# yum install httpd -y

[root@web2 ~]# mkdir -p /var/www/html/static

[root@web2 ~]# echo static 172.25.254.20 > /var/www/html/static/index.html

[root@web2 ~]# systemctl start httpd
bash 复制代码
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
    listen 80;
    server_name www.huazi.org;
    location ~ \.php$ {
        proxy_pass http://172.25.254.10:80;
    }
    location /static {
        proxy_pass http://172.25.254.20:80;
    }
}

[root@nginx-node1 ~]# nginx -s reload

测试

案例反向代理缓存功能

  • proxy_cache zone_name | off; 默认off 指明调用的缓存,或关闭缓存机制
  • zone_name表示缓存的名称,需要由proxy_cache_path事先定义
  • proxy_cache_key string 缓存中用于"键"的内容,默认值:proxy_cache_key $scheme$proxy_host$request_uri;
  • proxy_cache_valid [code ...] time; 定义对特定响应码的响应内容的缓存时长,定义在http{...}中
  • 示例: proxy_cache_valid 200 302 10m; 对于 HTTP 响应状态码为 200(OK)和 302(Found,通常用于临时重定向)的响应,它们将被缓存,并且缓存有效期为 10 分钟(10m)
  • proxy_cache_path 路径 定义可用于proxy功能的缓存
  • proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ; 默认是off 在被代理的后端服务器出现哪种情况下,可直接使用过期的缓存响应给客户端
  • 示例 proxy_cache_use_stale error http_502 http_503;
  • proxy_cache_methods GET | HEAD | POST ...; 对哪些客户端请求方法对应的响应进行缓存,GET和HEAD方法总是被缓存
bash 复制代码
#示例:在http配置定义缓存信息
proxy_cache_path  /var/cache/nginx/proxy_cache  levels=1:2:2  keys_zone=proxycache:20m  inactive=120s   max_size=10g;

#/var/cache/nginx/proxy_cache  定义缓存保存路径,proxy_cache会自动创建
#levels=1:2:2  定义缓存目录结构层次,1:2:2可以生成2^4x2^8x2^8=2^20=1048576个目录
#keys_zone=proxycache:20m   定义了一个名为proxycache的缓存键区域,并为其分配了20MB的内存,一般1M可存放8000个左右的key
#inactive=120s    缓存有效时间
#max_size=10g    最大磁盘占用空间,磁盘存入文件内容的缓存空间最大值

#调用缓存功能,需要定义在相应的配置段,如server{...};或者location等
proxy_cache proxycache;
proxy_cache_key $request_uri; #对指定的数据进行MD5的运算做为缓存的key
proxy_cache_valid 200 302 301 10m; #指定的状态码返回的数据缓存多长时间,10分钟
proxy_cache_valid any 1m; #除指定的状态码返回的数据以外的缓存多长时间,必须设置,否则不会缓存

非缓存场景下测压

bash 复制代码
[root@web2 ~]# ab -n 1000 -c 100 http://www.huazi.org/static/index.html

准备缓存

  • 在主配置文件中
bash 复制代码
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
  • proxycache名字可以自定义
bash 复制代码
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhosts.conf
bash 复制代码
[root@nginx-node1 ~]# nginx -s reload

缓存场景下测压

bash 复制代码
[root@web2 ~]# ab -n 1000 -c 100 http://www.huazi.org/static/index.html
  • 发现请求变快了

验证缓存文件

反向代理负载均衡(7层)

  • 官方文档https://nginx.org/en/docs/http/ngx_http_upstream_module.html
  • 上面的案例Nginx可以将客户端请求转发至单台后端服务器但是无法转发特定的一组服务器,而且不能对后端服务器提供相应的服务器状态监测
  • Nginx可以基于ngx_http_upstream_module模块提供服务器分组转发、权重分配、状态监测、调度算法高级功能

upstream配置参数

bash 复制代码
http {
	upstream name {
		server ip:port [params];
		......................
	}
	server {
		location / {
			proxy_pass   http://name;
		}
	}
}
  • upstream中的server支持的params如下
bash 复制代码
weight=number   #设置权重,默认为1,实现类似于LVS中的WRR,WLC等
max_conns=number   #给当前后端server设置最大活动链接数,默认为0表示没有限制
max_fails=number   #后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非周期性的探测
fail_timeout=time   #后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒
backup   #设置为备份服务器,当所有后端服务器不可用时,才会启用此备用服务器
down    #标记为down状态,可以平滑下线后端服务器
resolve   #当server定义的是主机名的时候,当A记录发生变化会自动应用新IP而不用重启

负载均衡算法

Nginx支持多种负载均衡算法常见的包括

  • 轮询Round Robin):默认算法,按照顺序请求依次分发到后端服务器
  • 权重Weighted Round Robin):为每个后端服务器设置权重权重高服务器分配的请求更多
  • IP 哈希ip_hash):根据客户端 IP 哈希值决定分发到哪台后端服务器,适用于需要保持会话一致性场景
  • 最少连接least_conn):将请求分配给当前连接数最少后端服务器
  • hash指定字段哈希):基于指定请求字段(如URL、Cookie等)来分配请求

案例:反向代理多台web服务器轮询

  • 需要location块中的proxy_pass参数upstream块配合使用
  • upstream块server块同级的
bash 复制代码
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhosts.conf
upstream webcluster {
    server 172.25.254.10:80 fail_timeout=15s max_fails=3;
    server 172.25.254.20:80 fail_timeout=15s max_fails=3;
    server 172.25.254.100:80 backup;
}

server {
    listen 80;
    server_name www.huazi.org;
    location / {
        proxy_pass  http://webcluster;
    }
}
  • max_fails=number 后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非周期性的探测
  • fail_timeout=time 后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用如果发现可用,则将后端服务器参与调度,默认为10秒
  • backup关键字意味着只有当webcluster组中的其他所有服务器不可用时,Nginx才会向这个服务器发送请求
bash 复制代码
[root@nginx-node1 ~]# nginx -s reload

测试:

案例:反向代理多台web服务器源地址hash调度

  • ip_hash,就不能有backup
bash 复制代码
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhosts.conf
upstream webcluster {
    ip_hash;
    server 172.25.254.10:80 fail_timeout=15s max_fails=3;
    server 172.25.254.20:80 fail_timeout=15s max_fails=3;
}

server {
    listen 80;
    server_name www.huazi.org;
    location / {
        proxy_pass  http://webcluster;
    }
}
bash 复制代码
[root@nginx-node1 ~]# nginx -s reload

测试:

案例:反向代理多台web服务器对uri进行hash调度

bash 复制代码
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhosts.conf
upstream webcluster {
    hash $request_uri consistent;
    server 172.25.254.10:80 fail_timeout=15s max_fails=3;
    server 172.25.254.20:80 fail_timeout=15s max_fails=3;
}

server {
    listen 80;
    server_name www.huazi.org;
    location / {
        proxy_pass  http://webcluster;
    }
}

[root@nginx-node1 ~]# nginx -s reload
bash 复制代码
[root@web1 ~]# mkdir -p /var/www/html/static/
[root@web1 ~]# echo 172.25.254.10 static > /var/www/html/static/index.html

案例:反向代理多台web服务器对cookie值进行hash调度

bash 复制代码
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhosts.conf
upstream webcluster {
    hash $cookie_huazi;
    server 172.25.254.10:80 fail_timeout=15s max_fails=3;
    server 172.25.254.20:80 fail_timeout=15s max_fails=3;
}

server {
    listen 80;
    server_name www.huazi.org;
    location / {
        proxy_pass  http://webcluster;
    }
}


[root@nginx-node1 ~]# nginx -s reload

案例:反向代理多台web服务器下线

bash 复制代码
upstream webcluster {
    hash $cookie_huazi;
    server 172.25.254.10:80 fail_timeout=15s max_fails=3 down;
    server 172.25.254.20:80 fail_timeout=15s max_fails=3;
}

server {
    listen 80;
    server_name www.huazi.org;
    location / {
        proxy_pass  http://webcluster;
    }
}

[root@nginx-node1 ~]# nginx -s reload

反向代理负载均衡(4层)

bash 复制代码
stream {
    upstream backend {
        server backend1.example.com:3306;
        server backend2.example.com:3306;
    }

    server {
        listen 3306;
        proxy_pass backend;
    }
}
  • Nginx1.9.0版本开始支持tcp模式负载均衡,在1.9.13版本开始支持udp协议负载udp主要用于DNS域名解析,其配置方式指令http代理类似,其基于ngx_stream_proxy_module模块实现tcp负载,另外基于模块ngx_stream_upstream_module实现后端服务器分组转发、权重分配、状态监测、调度算法等高级功能
  • 如果编译安装,需要指定--with-stream选项才能支持ngx_stream_proxy_module模块
  • 官方文档https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html

案例基于udpdns的负载均衡

  • nginx服务器172.25.254.100 www.huazi.org
  • dns1服务器172.25.254.10
  • dns2服务器172.25.254.20

先配置dns服务器

bash 复制代码
[root@web1 ~]# yum install bind -y

[root@web1 ~]# vim /etc/named.conf
bash 复制代码
[root@web1 ~]# vim /etc/named.rfc1912.zones
bash 复制代码
[root@web1 ~]# cd /var/named/
[root@web1 named]# cp -a named.localhost /var/named/huazi.com.zone
[root@web1 named]# vim huazi.com.zone
bash 复制代码
[root@web1 named]# systemctl start named

[root@web1 named]# dig www.huazi.com @172.25.254.10
bash 复制代码
[root@web2 ~]# yum install bind -y

[root@web2 ~]# vim /etc/named.conf
bash 复制代码
[root@web2 ~]# vim /etc/named.rfc1912.zones
bash 复制代码
[root@web2 ~]# cd /var/named/
[root@web2 named]# cp -a named.localhost /var/named/huazi.com.zone
[root@web2 named]# vim huazi.com.zone
bash 复制代码
[root@web2 named]# systemctl start named

[root@web2 named]# dig www.huazi.com @172.25.254.20

nginx配置

  • udp和tcp的负载均衡要写在http块之外
bash 复制代码
#修改主配置文件
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
bash 复制代码
[root@nginx-node1 ~]# mkdir -p /usr/local/nginx/tcpconf.d/

[root@nginx-node1 ~]# vim /usr/local/nginx/tcpconf.d/dns.conf
stream {
    upstream dns {
        server 172.25.254.10:53 fail_timeout=15s max_fails=3;
        server 172.25.254.20:53 fail_timeout=15s max_fails=3;
    }
    server {
        listen 53 udp reuseport;
        proxy_timeout 20s;
        proxy_pass dns;
    }
}


[root@nginx-node1 ~]# nginx -s reload

测试

  • 100上没有dns服务dig却可以指定100,通过100进行代理

案例基于tcpMySQL的负载均衡

  • nginx服务器172.25.254.100 www.huazi.org
  • MySQL1服务器172.25.254.10
  • MySQL2服务器172.25.254.20

数据库配置

bash 复制代码
[root@web1 ~]# yum install mariadb-server -y

[root@web2 ~]# yum install mariadb-server -y
bash 复制代码
[root@web1 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
bash 复制代码
[root@web2 ~]# vim /etc/my.cnf.d/mariadb-server.cnf



nginx配置

bash 复制代码
[root@nginx-node1 ~]# vim /usr/local/nginx/tcpconf.d/dns.conf
bash 复制代码
[root@nginx-node1 ~]# nginx -s reload
  • 下载MySQL的客户端
bash 复制代码
[root@nginx-node1 ~]# yum install mariadb -y

测试

相关推荐
迃幵chen9 分钟前
高可用虚拟IP-keepalived
linux·服务器·tcp/ip
苹果醋334 分钟前
MySQL Binlog 同步工具go-mysql-transfer Lua模块使用说明
java·运维·spring boot·mysql·nginx
猫猫的小茶馆1 小时前
【IO编程】标准IO和文件IO的对比
linux·c语言·嵌入式硬件·microsoft·嵌入式实时数据库
学Linux的语莫1 小时前
k8s之pod生命周期
linux·运维·docker·容器·kubernetes
petunsecn1 小时前
Jenkins触发器--在其他项目执行后构建
运维·jenkins
启明真纳1 小时前
k8s物料清单工具——KubeClarity
linux·运维·云原生·容器·kubernetes·云计算
wanhengidc1 小时前
国内大带宽服务器的应用场景
运维·服务器
weisian1512 小时前
Mysql--运维篇--主从复制和集群(主从复制I/O线程,SQL线程,二进制日志,中继日志,集群NDB)
运维·sql·mysql
肉三2 小时前
安装 Jenkins 后无法访问用户名或密码且忘记这些凭证怎么办?
运维·servlet·jenkins
誓约酱2 小时前
Linux下文件操作相关接口
linux·运维·服务器·c语言·c++·后端