一、Nginx 四、七层反代总结
1、反向代理介绍
反向代理:反向代理也叫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协议转发⾄指定服务器处理。
2、反向代理配置参数
proxy_pass;
#用来设置客户端请求转发给后端服务器的主机,可以是主机名、IP地址:端口的形式,也可以代理到预先设置的主机群主,需要模块gx_http_upstream_module⽀持
示例:
location /web {
index index.html;
proxy_pass http://10.10.100.102:80;
#不带斜线将访问的/web,等于访问后端服务器 http://10.10.100.102:80/web/index.html,即后端服务器配置的站点根⽬录要有web⽬录才可以被访问,这是⼀个追加/web到后端服务器
proxy_pass http://192.168.200.10:80/;
#带斜线,等于访问后端服务器的http://192.168.7.103:80/index.html 内容返回给客⼾端
}
proxy_hide_heard field;
#⽤于nginx作为反向代理的时候,在返回给客⼾端http响应的时候,隐藏后端服务版本相应头部的信息,可以设置在http/server或location块,
示例:
location /web {
index index.html;
proxy_pass http://10.10.100.102:80/;
proxy_hide_header ETag;
}
proxy_pass_header field;
#默认nginx在响应报⽂中不传递后端服务器的⾸部字段Date, Server, X-Pad, X-Accel等参数,如果要传递的话则要使⽤ proxy_pass_header field声明将后端服务器返回的值传递给客⼾端。
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 $remote_addr;
#添加HOST到报⽂头部,如果客⼾端为NAT上⽹那么其值为客⼾端的共⽤的公⽹IP地址,常⽤于在⽇之中记录客⼾端的真实IP地址。
proxy_connect_timeout time;
#配置nginx服务器与后端服务器尝试建⽴连接的超时时间,默认为60秒,⽤法如下:
proxy_connect_timeout 60s;
#60s为⾃定义nginx与后端服务器建⽴连接的超时时间
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_headers_hash_bucket_size 128;
#当配置了 proxy_hide_header和proxy_set_header的时候,⽤于设置nginx保存HTTP报⽂头的hash表的上限。
proxy_headers_hash_max_size 512;
#设置proxy_headers_hash_bucket_size的最⼤可⽤空间
server_namse_hash_bucket_size 512;
#server_name hash表申请空间⼤⼩
server_names_hash_max_szie 512;
#设置服务器名称hash表的上限⼤⼩
3、反向代理实例
3.1、 反向代理⽰例–单台web服务器:
server {
listen 80;
server_name wwww.cwy.com;
location / {
proxy_pass http://10.10.100.102:80/;
}
3.2、 反向代理⽰例–指定location:
[root@node1 nginx]# cat conf/nginx.conf
server {
listen 80;
server_name www.cwy.com;
location / {
root /apps/nginx/html/pc;
index index.html index.htm;
}
location /web {
proxy_pass http://10.10.100.102:80;
}
#代理服务器测试页面
[root@node1 nginx]# cat /apps/nginx/html/pc/index.html
pc test
[root@node1 nginx]# cat /apps/nginx/html/web/index.html
web01 test
#后端服务测试页面
[root@node2 nginx]# cat /apps/nginx/html/web/index.html
web02 test
#直接访问域名返回的是代理服务器自己的页面
[root@node1 nginx]# curl -L www.cwy.com
pc test
#访问www.cflinux.com/web返回后端被代理服务器的页面
[root@node1 nginx]# curl -L www.cwy.com/web
web02 test
3.3、 反向代理⽰例–缓存功能:
proxy_cache zone | off; 默认off
#指明调⽤的缓存,或关闭缓存机制;Context:http, server, location
proxy_cache_key string;
#缓存中⽤于“键”的内容,默认值:proxy_cache_key $scheme$proxy_host$request_uri;
proxy_cache_valid [code ...] time;
#定义对特定响应码的响应内容的缓存时⻓,定义在http{...}中
⽰例:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_path;
#定义可⽤于proxy功能的缓存;Context:http
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; #最⼤磁盘占⽤空间,磁盘存⼊⽂件内容的缓存空间最⼤值
#调⽤缓存功能,需要定义在相应的配置段,如server{...};或者location等
proxy_cache proxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 10m; #指定的状态码返回的数据缓存多⻓时间
proxy_cache_valid any 1m;
proxy_cache_use_stale error http_502 http_503; #在被代理的后端服务器出现哪种情况下,可直接使⽤过期的缓存响应客⼾端
#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⽅法总是被缓存
3.3.1、 非缓存场景压测
#准备测试页面
[root@node2 nginx]# cp /var/log/messages /apps/nginx/html/web/log.html
[root@node1 nginx]# ab -n2000 -c200 http://www.cwy.com/web/log.html
Concurrency Level: 200
Time taken for tests: 11.701 seconds
Complete requests: 2000
Failed requests: 0
Write errors: 0
Total transferred: 1733102000 bytes
HTML transferred: 1732626000 bytes
Requests per second: 170.93 [#/sec] (mean)
Time per request: 1170.065 [ms] (mean)
Time per request: 5.850 [ms] (mean, across all concurrent requests)
Transfer rate: 144648.54 [Kbytes/sec] received
3.3.2、 准备缓存配置
[root@node1 nginx]# vim conf/nginx.conf
#配置在nginx.conf的http配置段
proxy_cache_path /appsinx/proxycache levels=1:1:1 keys_zone=proxycache:20m inactive=120s max_size=1g;
#server段配置
location /web {
proxy_pass http://124.71.6.126:80;
#配置在要缓存的url下,或者放在sever配置段对所有url生效
proxy_set_header clientip $remote_addr;
proxy_cache proxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 1h;
proxy_cache_valid any 1m;
}
[root@node1 nginx]# sbin/nginx -s reload
#访问并验证
[root@node1 nginx]# http://www.cwy.com/web/log.html
[root@node1 nginx]# ab -n2000 -c200 http://www.cwy.com/web/log.html
Concurrency Level: 200
Time taken for tests: 0.342 seconds
Complete requests: 2000
Failed requests: 0
Write errors: 0
Total transferred: 1733102000 bytes
HTML transferred: 1732626000 bytes
Requests per second: 5856.04 [#/sec] (mean)
Time per request: 34.153 [ms] (mean)
Time per request: 0.171 [ms] (mean, across all concurrent requests)
Transfer rate: 4955618.34 [Kbytes/sec] received
#查看缓存目录
[root@node1 nginx]# tree proxycache/
proxycache/
├── 1
│ └── 9
│ └── 7
└── f
└── 0
└── 6
└── 50b643197ae7d66aaaa5e7e1961b060f
[root@node1 nginx]# head -n100 proxycache/f/0/6/50b643197ae7d66aaaa5e7e1961b060f
▒J▒`h0▒`q<▒`▒▒▒dR"60e83068-d3809"
KEY: /web/log.html
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Fri, 09 Jul 2021 12:09:22 GMT
Content-Type: text/html
Content-Length: 866313
Last-Modified: Fri, 09 Jul 2021 11:18:00 GMT
Connection: close
ETag: "60e83068-d3809"
Accept-Ranges: bytes
3.3.3、添加头部报文信息
nginx基于模块ngx_http_headers_module可以实现对头部报⽂添加指定的key与值, https://nginx.org/en/docs/http/ngx_http_headers_module.html
Syntax: add_header name value [always];
Default: —
Context: http, server, location, if in location
#添加⾃定义⾸部,如下:
add_header name value [always];
add_header X-Via $server_addr;
add_header X-Cache $upstream_cache_status;
add_header X-Accel $server_name;
#添加⾃定义响应信息的尾部, 1.13.2版后⽀持
add_trailer name value [always];
3.3.4、Nginx配置:
location /web {
proxy_pass http://10.10.100.102:80;
proxy_set_header clientip $remote_addr;
proxy_cache proxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 1h;
proxy_cache_valid any 1m;
add_header X-Via $server_addr;
add_header X-Cache $upstream_cache_status;
add_header X-Accel $server_name;
}
4、Nginx http 反向代理⾼级应⽤:
如上介绍Nginx可以将客⼾端的请求转发⾄单台后端服务器但是⽆法转发⾄特定的⼀组的服务器,⽽且不能对后端服务器提供相应的服务器状态监测,但是Nginx可以基于ngx_http_upstream_module模块提供服务器分组转发、权重分配、状态监测、调度算法等⾼级功能,官⽅⽂档: https://nginx.org/en/docs/http/ngx_http_upstream_module.html
4.1、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基于取模运算。
hash $request_uri consistent; #基于⽤⼾请求的uri做hash
ip_hash; #源地址hash调度⽅法,基于的客⼾端的remote_addr(源地址)做hash计算,以实现会话保持
least_conn; #最少连接调度算法,优先将客⼾端请求调度到当前连接最少的后端服务器
4.2、反向代理⽰例–多台web服务器:
#http段配置
upstream webserver {
server 10.10.100.102:80 weight=1 fail_timeout=5s max_fails=3;
server 10.10.100.103:80 weight=1 fail_timeout=5s max_fails=3;
server 10.10.100.104:80 weight=1 fail_timeout=5s max_fails=3 backup;
}
#server段配置
location /web {
proxy_pass http://webserver;
index index.html;
}
#测试
[root@node1 nginx]# while true;do curl -L http://www.cwy.com/web/index.html ;sleep 1;done
web02 10.10.100.102
web03 10.10.100.103
web02 10.10.100.102
web03 10.10.100.103
web02 10.10.100.102
web03 10.10.100.103
#关闭10.10.100.102、10.10.100.103 测试nginx backup服务器可⽤性:
[root@node1 nginx]# while true;do curl -L http://www.cwy.com/web/ ;sleep 1;done
web02 10.10.100.102
web03 10.10.100.103
web02 10.10.100.102
web03 10.10.100.103
backup 10.10.100.104
backup 10.10.100.104
backup 10.10.100.104
4.3、反向代理⽰例–客⼾端IP透传:
upstream webserver {
# server 10.10.100.102:80 weight=1 fail_timeout=5s max_fails=3;
server 10.10.100.103:80 weight=1 fail_timeout=5s max_fails=3;
server 10.10.100.104:80 weight=1 fail_timeout=5s max_fails=3 backup;
}
location /web {
proxy_pass http://webserver;
index index.html;
#添加客⼾端IP到报文头部
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
#后端web服务器配置
#1、Apache:
vim /etc/httpd/conf/httpd.conf LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{UserAgent}i\"" combined
#2、Nginx:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
#nginx默认日志格式就有$http_x_forwarded_for
#访问验证
[root@node2 nginx]# curl -L http://www.cwy.com/web/
web03 10.10.100.103
#查看日志
[root@node3 nginx]# tail -f logs/access.log
10.10.100.101 - - [10/Jul/2021:03:01:00 +0800] "GET /web/ HTTP/1.0" 200 20 "-" "curl/7.29.0" "10.10.100.102"
#10.10.100.102为客户端ip
5、实现Nginx tcp负载均衡:
Nginx在1.9.0版本开始⽀持tcp模式的负载均衡,在1.9.13版本开始⽀持udp协议的负载,udp主要⽤于DNS的域名解析,其配置⽅式和指令和http 代理类似,其基于ngx_stream_proxy_module模块实现tcp负载,另外基于模块ngx_stream_upstream_module实现后端服务器分组转发、权重分配、状态监测、调度算法等⾼级功能。
官⽅⽂档:https://nginx.org/en/docs/stream/ngx_stream_core_module.html
5.1、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 10.10.100.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;
}
}
5.2、负载均衡实例–Redis:
#安装redis
[root@node2 ~]# yum install redis -y
[root@node2 ~]# vim /etc/redis.conf
bind 0.0.0.0
[root@node2 ~]# systemctl start redis
[root@node2 ~]# ss -tnl|grep 6379
LISTEN 0 128 *:6379 *:*
#代理服务器nginx添加配置
[root@node1 ~]# mkdir /apps/nginx/conf/tcp
[root@node1 ~]# vim /apps/nginx/conf/tcp/tcp.conf
stream {
upstream redis_server {
server 10.10.100.102:6379 max_fails=3 fail_timeout=30s;
}
server {
listen 10.10.100.101:6379;
proxy_connect_timeout 3s;
proxy_timeout 3s;
proxy_pass redis_server;
}
}
[root@node1 ~]# vim /apps/nginx/conf/nginx.conf
#改配置与http模块平级
include /apps/nginx/conf/tcp/tcp.conf;
#重启nginx
[root@node1 ~]# /apps/nginx/sbin/nginx -s reload
[root@node1 ~]# ss -tnl|grep 6379
LISTEN 0 128 10.10.100.101:6379 *:*
#测试
[root@node1 ~]# redis-cli -h 10.10.100.101
10.10.100.101:6379> set name jack
OK
10.10.100.101:6379> get name
"jack"
10.10.100.101:6379>