Nginx反向代理
反向代理:反向代理也叫reverse proxy,指的是代理外网用户的请求到内部的指定web服务器,并将数据返回给用户的一种方式,这是用的比较多的一种方式。
Nginx除了可以在企业提供高性能的web服务之外,另外还可以将本身不具备的请求通过某种预定义的协议转发至其它服务器处理,不同的协议就是Nginx服务器与其他服务器进行通信的一种规范,主要在不同的场景使用以下模块实现不同的功能:
ngx_http_proxy_module: 将客户端的请求以http协议转发至指定服务器进行处理。
ngx_stream_proxy_module:将客户端的请求以tcp协议转发至指定服务器处理。
ngx_http_fastcgi_module:将客户端对php的请求以fastcgi协议转发至指定服务器助理。
ngx_http_uwsgi_module:将客户端对Python的请求以uwsgi协议转发至指定服务器处理。
Nginx http的反向代理实现
反向代理配置参数
- proxy_pass; 用来设置将客户端请求转发给的后端服务器的主机,可以是主机名、IP地址:端口的方式,也可以代理到预先设置的主机群组,需要模块gx_http_upstream_module支持。
server {
listen 80;
charset utf-8;
server_name www.a.com;
location /app {
proxy_pass http://192.168.36.110:80; # 不带斜线将访问的/web,等于访问后端服务器 http://192.168.36.103:80/web/index.html,即后端服务器配置的站点根目录要有web目录才可以被访问,这是一个追加/web到后端服务器。 带斜线,等于访问后端服务器的http://192.168.36.103:80/index.html 内容返回给客户端
index index.html;
}
}
访问测试
[root@CentOS7 conf.d]#curl -L -i http://www.a.com/app
HTTP/1.1 301 Moved Permanently
Server: Darius/10.0
Date: Sat, 01 Jun 2019 08:24:33 GMT
Content-Type: text/html; charset=iso-8859-1
Content-Length: 234
Connection: keep-alive
Location: http://192.168.36.110/app/
HTTP/1.1 200 OK
Date: Sat, 01 Jun 2019 08:24:31 GMT
Server: Apache/2.4.6 (CentOS)
Last-Modified: Sat, 25 May 2019 03:41:28 GMT
ETag: "19-589ae171491d6"
Accept-Ranges: bytes
Content-Length: 25
Content-Type: text/html; charset=UTF-8
Real Server 110
- proxy_hide_header; 用于nginx作为反向代理的时候,在返回给客户端http响应的时候,隐藏后端服务版本相应头部的信息,可以设置在http/server或location块
[root@CentOS7 conf.d]#vim a.conf
server {
listen 80;
charset utf-8;
server_name www.a.com;
location /app {
index index.html;
proxy_pass http://192.168.36.110:80;
proxy_hide_header Location; # 若想隐藏多个head头部信息需要再次定义proxy_hide_header,不支持在后面接着写
}
}
[root@CentOS7 conf.d]#nginx -s reload
[root@CentOS7 conf.d]#curl -L -I http://www.a.com/app
HTTP/1.1 301 Moved Permanently
Server: Darius/10.0
Date: Sat, 01 Jun 2019 08:30:47 GMT
Content-Type: text/html; charset=iso-8859-1
Connection: keep-alive
- proxy_pass_request_body on | off; 是否向后端服务器发送HTTP包体部分,可以设置在http/server或location块,默认即为开启
- proxy_pass_request_headers on | off; 是否将客户端的请求头部转发给后端服务器,可以设置在http/server或location块,默认即为开启
- proxy_set_header; 可以更改或添加客户端的请求头部信息内容并转发至后端服务器,比如在后端服务器想要获取客户端的真实IP的时候,就要更改每一个报文的头部,如下:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # proxy_set_header HOST $remote_addr; # 添加HOST到报文头部,如果客户端为NAT上网那么其值为客户端的共用的公网IP地址。
- proxy_hide_header field; 用于隐藏后端服务器特定的响应首部,默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, XPad, X-Accel等
- proxy_connect_timeout time; 配置nginx服务器与后端服务器尝试建立连接的超时时间,默认为60秒
proxy_connect_timeout 60s; # 60s为自定义nginx与后端服务器建立连接的超时时间
- proxy_read_time time; 配置nginx服务器向后端服务器或服务器组发起read请求后,等待的超时时间,默认60s
proxy_send_time 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_headers_hash_bucket_size 64; 当配置了 proxy_hide_header和proxy_set_header的时候,用于设置nginx保存HTTP报文头的hash表的上限。
- proxy_headers_hash_max_size 512; 设置proxy_headers_hash_bucket_size的最大可用空间
- server_names_hash_bucket_size 512; server_name hash表申请空间大小
- server_names_hash_max_szie 512; 设置服务器名称hash表的上限大小
反向代理--缓存功能
- proxy_cache zone | off; 默认off 指明调用的缓存,或关闭缓存机制
- proxy_cache_key string; 缓存中用于“键”的内容,默认值:proxy_cache_key $scheme$proxy_host$request_uri;
- proxy_cache_valid [code ...] time; 定义对特定响应码的响应内容的缓存时长,定义在http{...}中
示例 # 调用缓存功能,需要定义在相应的配置段,如server{...};或者location等 proxy_cache proxycache; proxy_cache_key $request_uri; proxy_cache_valid 200 302 10m; # 对200、302类响应码缓存10分钟 proxy_cache_valid 404 1m; # 对404类响应码缓存1分钟
- proxy_cache_path; 定义可用于proxy功能的缓存;
使用方法: proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
示例:在http配置定义缓存信息
proxy_cache_path /var/cache/nginx/proxy_cache # 定义缓存保存路径,proxy_cache会自动创
建
levels=1:2:2; # 定义缓存目录结构层次,1:2:2可以生成2^4x2^8x2^8=1048576个目录
keys_zone=proxycache:20m; # 指内存中缓存的大小,主要用于存放key和metadata(如:使用次数)
inactive=120s; # 缓存有效时间
max_size=1g; # 最大磁盘占用空间,磁盘存入文件内容的缓存空间最大值
5. proxy_cache_use_stale; 在被代理的后端服务器出现哪种情况下,可直接使用过期的缓存响应客户端
```bash
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_methods GET | HEAD | POST ...; 对哪些客户端请求方法对应的响应进行缓存,GET和HEAD方法总是被缓存
- proxy_set_header field value; 设定发往后端主机的请求报文的请求首部的值
Context: http, server, location proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 请求报文的标准格式如下: X-Forwarded-For: client1, proxy1, proxy2
缓存配置
[root@CentOS7 conf.d]#vim ../conf/nginx.conf # 配置在nginx.conf http配置段
proxy_cache_path /data/nginx/proxycache levels=1:1:1 keys_zone=proxycache:20m inactive=120s max_size=1g;
[root@CentOS7 conf.d]#cat a.conf
server {
listen 80;
charset utf-8;
server_name www.a.com;
location /app { # 要缓存的URL或者放在server配置项对所有URL都进行缓存
index index.html;
proxy_pass http://192.168.36.110:80;
proxy_hide_header Location;
proxy_hide_header Connection;
proxy_set_header clientip $remote_addr;
proxy_cache proxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 10m;
proxy_cache_valid any 1m;
}
}
[root@CentOS7 conf.d]#nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@CentOS7 conf.d]#nginx -s reload
访问验证
[root@CentOS7 conf.d]#curl -L http://www.a.com/app
[root@CentOS7 conf.d]#ab -n 2000 -c 200 http://www.a.com/app
Total transferred: 822000 bytes
HTML transferred: 468000 bytes
Requests per second: 9413.58 [#/sec] (mean)
Time per request: 21.246 [ms] (mean)
Time per request: 0.106 [ms] (mean, across all concurrent requests)
Transfer rate: 3778.30 [Kbytes/sec] received
# 缓存路径结构及文件大小
[root@CentOS7 conf.d]#tree /data/nginx/proxycache/
/data/nginx/proxycache/
├── 2
│ └── e
│ └── 8
└── 7
└── 5
└── b
└── 606c5106afffe9fd4f2021504afe7b57
6 directories, 1 file
验证文件内容
[root@CentOS7 conf.d]#head -n100 /data/nginx/proxycache/7/5/b/606c5106afffe9fd4f2021504afe7b57
HTTP/1.1 200 OK
Date: Sat, 01 Jun 2019 09:51:06 GMT
Server: Apache/2.4.6 (CentOS)
Last-Modified: Sat, 01 Jun 2019 09:50:35 GMT
ETag: "1388-58a4010131b0d"
Accept-Ranges: bytes
Content-Length: 5000
Connection: close
Content-Type: text/html; charset=UTF-8
添加自定义头部信息
nginx基于模块ngx_http_headers_module可以实现对头部报文添加指定的key与值
# 添加自定义首部,如下:
add_header name value [always];
add_header X-Via $server_addr;
add_header X-Cache $upstream_cache_status;
add_header X-Accel $server_name;
add_trailer name value [always];
添加自定义响应信息的尾部, 1.13.2版后支持
Nginx配置
[root@CentOS7 conf.d]#cat a.conf
server {
listen 80;
charset utf-8;
server_name www.a.com;
location /app {
index index.html;
proxy_pass http://192.168.36.110:80;
proxy_set_header clientip $remote_addr;
proxy_cache proxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 10m;
proxy_cache_valid any 1m;
add_header X-Via $server_addr;
add_header X-Cache $upstream_cache_status;
add_header X-Accel $server_name;
}
}
[root@CentOS7 conf.d]#nginx -s reload
[root@CentOS7 conf.d]#curl -i http://www.a.com/app
HTTP/1.1 301 Moved Permanently
Server: Darius/10.0
Date: Sat, 01 Jun 2019 10:12:16 GMT
Content-Type: text/html; charset=iso-8859-1
Content-Length: 234
Connection: keep-alive
Location: http://192.168.36.110/app/
X-Via: 192.168.36.104
X-Cache: MISS # 第一次访问没有使用缓存,再次进行访问测试
X-Accel: www.a.com
[root@CentOS7 conf.d]#curl -i http://www.a.com/app
HTTP/1.1 301 Moved Permanently
Server: Darius/10.0
Date: Sat, 01 Jun 2019 10:12:18 GMT
Content-Type: text/html; charset=iso-8859-1
Content-Length: 234
Connection: keep-alive
Location: http://192.168.36.110/app/
X-Via: 192.168.36.104
X-Cache: HIT # 第二次访问命中缓存
X-Accel: www.a.com
Nginx http反向代理高级应用
Nginx可以基于ngx_http_upstream_module模块提供服务器分组转发、权重分配、状态监测、调度算法等高级功能
http upstream 配置参数
upstream name {
}
# 自定义一组服务器,配置在http内
server address [parameters];
# 配置一个后端web服务器,配置在upstream内,至少要有一个server服务器配置。
# server支持的parameters如下:
weight=number # 设置权重,默认为1。
max_conns=number # 给当前server设置最大活动链接数,默认为0表示没有限制。
max_fails=number # 对后端服务器连续监测失败多少次就标记为不可用。
fail_timeout=time # 对后端服务器的单次监测超时时间,默认为10秒。
backup # 设置为备份服务器,当所有服务器不可用时将重新启用次服务器。
down # 标记为down状态。
resolve # 当server定义的是主机名的时候,当A记录发生变化会自动应用新IP而不用重启Nginx。
hash KEY consistent;
# 基于指定key做hash计算,使用consistent参数,将使用ketama一致性hash算法,适用于后端是Cache服务器(如varnish)时使用,consistent定义使用一致性hash运算,一致性hash基于取模运算。
# 所谓取模运算,就是计算两个数相除之后的余数,比如10%7=3, 7%4=3
hash $request_uri consistent; # 基于用户请求的uri做hash
ip_hash; # 源地址hash调度方法,基于的客户端的remote_addr(源地址)做hash计算,以实现会话保持
least_conn; # 最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器
多台web服务器实现反向代理
[root@CentOS7 conf.d]#vim ../conf/nginx.conf
upstream app1 {
#hash $request_uri consistent;
#ip_hash; # 指定ip_hash算法,根据session调度到同一台后端主机上,当此台主机宕机,则强制切换到另一台存活的主机上
#least_conn;
server 192.168.36.110:80 weight=1 fail_timeout=5s max_fails=3; # 后端服务器状态监测:fail_timeout连续检测多少次失败,max_fails检测时长
server 192.168.36.106:80 weight=1 fail_timeout=5s max_fails=3;
server 192.168.36.101:80 weight=1 fail_timeout=5s max_fails=3 backup; # 备用服务器,当其余反向代理服务器宕机,启用备用服务器
}
[root@CentOS7 conf.d]#vim a.conf
server {
listen 80;
charset utf-8;
server_name www.a.com;
location / {
index index.html;
root /data/nginx/html/pc;
}
location /app {
index index.html;
proxy_pass http://app1;
}
}
[root@CentOS7 conf.d]#nginx -s reload
访问测试
[root@CentOS7 conf.d]#while true;do curl http://www.a.com/app/index.html;sleep 0.5;done
192.168.36.110
192.168.36.106
192.168.36.110
192.168.36.106
启用ip_hash算法
[root@CentOS7 conf.d]#vim ../conf/nginx.conf
upstream app1 {
#hash $request_uri consistent;
#least_conn;
server 192.168.36.110:80 weight=1 fail_timeout=5s max_fails=3;
server 192.168.36.106:80 weight=1 fail_timeout=5s max_fails=3;
ip_hash;
}
[root@CentOS7 conf.d]#nginx -s reload
访问测试:
[root@CentOS7 conf.d]#while true;do curl http://www.a.com/app/index.html;sleep 0.5;done
192.168.36.106
192.168.36.106
192.168.36.106
192.168.36.106
192.168.36.106
192.168.36.106
宕机测试
[root@CentOS7 conf.d]#while true;do curl http://www.a.com/app/index.html;sleep 0.5;done
192.168.36.106
192.168.36.106
192.168.36.106
192.168.36.106
192.168.36.110 # 请求被强制切换到存活主机上
192.168.36.110
....
192.168.36.106 # 当修复好宕机主机重新工作,请求将重新回到原来的主机上
192.168.36.106
192.168.36.106
Nginx动静分离
upstream web {
server 192.168.36.1 weight=1 max_fails=2 fail_timeout=2;
server 192.168.36.2 weight=1 max_fails=2 fail_timeout=2;
}
upstream image {
server 192.168.36.3 weight=1 max_fails=2 fail_timeout=2;
server 192.168.36.4 weight=1 max_fails=2 fail_timeout=2;
}
upstream php {
server 192.168.36.5 weight=1 max_fails=2 fail_timeout=2;
server 192.168.36.6 weight=1 max_fails=2 fail_timeout=2;
}
location /{
root html/web;
index index.php index.html;
}
location ~* \.php$ {
fastcgi_proxy http://php;
}
location ~* "\.(.jpg|png|jpeg|gif)" {
proxy_pass http://image;
}
Nginx Tcp负载均衡
Nginx在1.9.0版本开始支持tcp模式的负载均衡,在1.9.13版本开始支持udp协议的负载,udp主要用于DNS的域名解析,其配置方式和指令和http 代理类似,其基于ngx_stream_proxy_module模块实现tcp负载,另外基于模块ngx_stream_upstream_module实现后端服务器分组转发、权重分配、状态监测、调度算法等高级功能。
Tcp负载均衡配置参数
stream { #定义stream
upstream backend { #定义后端服务器
hash $remote_addr consistent; #定义调度算法
server backend1.example.com:12345 weight=5; #定义具体server
server 127.0.0.1:12345 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
}
upstream dns { #定义后端服务器
server 192.168.0.1:53535; #定义具体server
server dns.example.com:53;
}
server { #定义server
listen 12345; #监听IP:PORT
proxy_connect_timeout 1s; #连接超时时间
proxy_timeout 3s; #转发超时时间
proxy_pass backend; #转发到具体服务器组
}
server {
listen 127.0.0.1:53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}
server {
listen [::1]:12345;
proxy_pass unix:/tmp/stream.socket;
}
}
负载均衡实验环境
主机名称 | 主机IP | 运行服务 |
---|---|---|
CentOS7 | 192.168.36.104 | Nginx |
CentOS7-1 | 192.168.36.110 | Redis、Mysql |
基于Redis的负载均衡实例
安装并配置Redis服务
[root@CentOS7-1 ~]#yum install -y redis
[root@CentOS7-1 ~]#vim /etc/redis.conf
[root@CentOS7-1 ~]#egrep "^bind" /etc/redis.conf
bind 0.0.0.0
[root@CentOS7-1 ~]#systemctl start redis
[root@CentOS7-1 ~]#systemctl enable redis
Created symlink from /etc/systemd/system/multi-user.target.wants/redis.service to /usr/lib/systemd/system/redis.service.
[root@CentOS7-1 ~]#ss -ntl | grep 6379 # Redis基于6379端口进行工作
LISTEN 0 128 *:6379 *:*
Nginx配置
[root@CentOS7 ~]#mkdir /apps/nginx/tcp
[root@CentOS7 ~]#cd /apps/nginx/tcp/
[root@CentOS7 tcp]#vim tcp.conf
stream {
upstream redis_server {
server 192.168.36.110:6379 max_fails=3 fail_timeout=30s;
}
server {
listen 192.168.36.104:6379;
proxy_connect_timeout 3s;
proxy_timeout 3s;
proxy_pass redis_server;
}
}
[root@CentOS7 tcp]#vim ../conf/nginx.conf
include /apps/nginx/tcp/tcp.conf; # 注意此处的include与http模块平级,建议写在http模块上方
[root@CentOS7 tcp]#nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@CentOS7 tcp]#nginx -s reload
# 查看6379端口是否开启
[root@CentOS7 tcp]#ss -ntl | grep 6379
LISTEN 0 128 192.168.36.104:6379 *:*
# 测试通过Nginx负载连接Redis
[root@CentOS7-1 ~]#redis-cli -h 192.168.36.104
192.168.36.104:6379> set name darius
OK
192.168.36.104:6379> get name
"darius"
192.168.36.104:6379>
基于Mysql的负载均衡实例
服务器安装Mariadb
[root@CentOS7-1 ~]#yum install -y mariadb mariadb-server
[root@CentOS7-1 ~]#systemctl start mariadb # 启动mariadb数据库服务
[root@CentOS7-1 ~]#systemctl enable mariadb # 开机自启动数据库服务
[root@CentOS7-1 ~]#ss -ntl | grep 3306 # 检查端口是否启动
LISTEN 0 50 *:3306 *:*
Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service.
[root@CentOS7-1 ~]#mysql_secure_installation # 对数据库进行安全加固
# 对数据库进行授权操作
MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.36.%' IDENTIFIED BY 'centos';
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
Nginx配置
[root@CentOS7 tcp]#vim tcp.conf
stream {
upstream mysql_server {
least_conn;
server 192.168.36.110:3306 max_fails=3 fail_timeout=30s;
}
server {
listen 192.168.36.104:3306;
proxy_connect_timeout 3s;
proxy_timeout 3s;
proxy_pass mysql_server;
}
}
[root@CentOS7 tcp]#nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@CentOS7 tcp]#nginx -s reload
# 对负载端口进行检查
[root@CentOS7 tcp]#ss -ntl | grep 3306
LISTEN 0 128 192.168.36.104:3306 *:*
####测试通过nginx负载连接Mysql
[root@CentOS7-1 ~]#mysql -uroot -pcentos -h 192.168.36.104
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 16
Server version: 5.5.60-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> CREATE DATABASE Darius;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| Darius |
| mysql |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.00 sec)
MariaDB [(none)]>