七层代理
nginx做七层代理,可以代理多种七层协议,代理http为同构代理,代理异构的fastcgi、uwsgi等为异构代理;
http代理
https://nginx.org/en/docs/http/ngx_http_proxy_module.html
分别可以对php动态,http静态,python动态,四层tcp/udp 做代理
The ngx_http_fastcgi_module
module allows passing requests to a FastCGI server.
The ngx_http_proxy_module
module allows passing requests to another server.
The ngx_http_uwsgi_module
module allows passing requests to a uwsgi server.
The ngx_stream_proxy_module
module (1.9.0) allows proxying data streams over TCP, UDP (1.9.13), and UNIX-domain sockets.
后端是主机组
1,后端部署2个httpd
yum install -y httpd
echo host3 > /var/www/html/index.html
echo host4 > /var/www/html/index.html
#分别写入不同主页,然后启动
2,定义主机组,定义nginx的虚拟主机做主机组转发
vim nginx.conf
http {
...
upstream back1 {
server 192.168.80.102;
server 192.168.80.103;
}
...
}
#http段配置后端主机组,可以设置主机的权重,状态,调度算法,健康检测机制等;
[root@host2 conf]# cat vhosts/httpd-pro.conf
server {
listen 80;
server_name www.load1.com;
location / {
proxy_pass http://back1;
}
}
#做一个虚拟主机,然后引用刚定义的主机组;记得reload
3,测试
[root@host1 ~]# curl www.load1.com
host4
[root@host1 ~]# curl www.load1.com
host3
[root@host1 ~]# curl www.load1.com
host4
[root@host1 ~]# curl www.load1.com
host3
#默认算法是轮询调度
调度算法
- 轮询,默认算法;
- 当前最少连接;
- 源ip的hash;可以做会话的绑定
- 基于key的hash;对$request_uri的hash,适用于后端是varnish缓存的情况,利用提供缓存使用率;
http {
...
upstream back1 {
# least_conn;
ip_hash;
# round-robin;
# hash $reqeust_uri consistent;
hash $remote_addr;
hash $cookie_NAME; 对变量名是NAME的cookie做hash;
nginx默认支持4种调度算法,默认是轮询;
hash为generial hash,可以对一些变量做hash,consisten代表用一致性hash;$request_uri适用于对后端的varnish等缓存做反代的情况;提高缓存命中率;
# 另外,每台server后,可以设置weight权重、down或者backup的状态;
server 192.168.80.102;
server 192.168.80.103;
}
...
}
单节点、location为/
后端主机单节点,转发的location是/;会到后端节点的根网页文件目录寻找文件;
#
bbs虚拟主机:将对/的请求,都转发给102,102是httpd;
server {
listen 80;
server_name www.bbs.com;
location / {
#root /data/html/bbs;
#index index.html;
proxy_pass http://192.168.80.102;
}
}
#
[root@host1 ~]# curl www.bbs.com
bbs-index
reload后,再次访问,就变为102主页;
[root@host1 ~]# curl www.bbs.com
102-index
[root@host1 ~]# curl www.bbs.com
102-index
单节点,转发location带uri
1,转发配置
server {
listen 80;
server_name www.load1.com;
index index.html;
location /path {
proxy_pass http://192.168.80.103/;
# 一定以/结尾,否则会404 not found
}
}
2,后端文件
[root@host4 html]# echo 666 > 6.html
[root@host4 html]# ll
total 12
-rw-r--r-- 1 root root 4 Aug 30 13:38 6.html
3,访问
[root@host1 ~]# curl www.load1.com/path/6.html
666
[root@host1 ~]# curl 192.168.80.103/6.html
666
# 看到对/path/xx的访问转发为了对后端/xx的访问;
单节点,转发location带uri,目标节点带uri
1,配置转发,
server {
listen 80;
server_name www.load1.com;
index index.html;
location /path {
proxy_pass http://192.168.80.103/dir/;
}
}
# dir的uri,会覆盖掉path的uri
2,后端页面;
[root@host4 html]# cat path/1.html
path-1.html
[root@host4 html]# cat dir/1.html
dir
[root@host4 html]# ll
total 8
-rw-r--r-- 1 root root 7 Aug 30 13:27 1.html
drwxr-xr-x 2 root root 20 Aug 30 13:31 dir
-rw-r--r-- 1 root root 6 Aug 30 12:47 index.html
drwxr-xr-x 2 root root 38 Aug 30 13:27 path
2,访问
[root@host1 ~]# curl www.load1.com/path/1.html
dir
[root@host1 ~]# curl 192.168.80.103/dir/1.html
dir
# 可见:对www.load1.com/path/xx下的访问转发为了对192.168.80.103/dir/xx的访问
单节点,location用正则匹配,目标节点要以/结尾
1,转发配置
server {
listen 80;
server_name www.load1.com;
index index.html;
location ~ /path/ {
proxy_pass http://192.168.80.103;
}
}
# 103/后边不可以带uri,/根也不可以带,否则如下报错;
[root@host2 conf]# nginx -s reload
nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression
2,后端页面
[root@host4 html]# echo path-p > path/p/1.html
3,访问
[root@host1 ~]# curl www.load1.com/path/p/1.html
path-p
[root@host1 ~]# curl 192.168.80.103/path/p/1.html
path-p
#看到,~ 正则匹配,是将nginx和后端节点的uri都划上了等号;
fastcgi代理
0,实验环境:
nginx+php-fpm,不在同一个主机;
nginx:192.168.80.101
编译安装1.14.2版本
php-fpm:192.168.80.102
编译安装5.5.38版本
1,编译nginx
2,编辑php
3,配置nginx做fastcgi代理
location ~* \.php$ {
fastcgi_pass 192.168.80.102:9000;
# php-fpm地址和端口
fastcgi_index index.php;
# 后端php-fpm的默认页面
fastcgi_param SCRIPT_FILENAME /data/php$fastcgi_script_name;
# 传递给后端php-fpm的参数SCRIPT_FILENAME,参数值是/data/php$fastcgi_script_name;即:假如请求的是1.php文件,那么找的文件就是在php-fpm所在主机上,找/data/php/1.php文件,并执行,然后返回结果给nginx,再由nginx返回给客户端;
# 注意,文件是放在后端php-fpm上的,$fastcgi_script_name的值是请求的uri,如/1.php
include fastcgi_params;
# 引入nginx配置目录下的fastcgi_params参数文件;
}
location ~* ^/(ping|status)$ {
fastcgi_pass 192.168.80.102:9000;
fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
include fastcgi_params;
# 同上,由于ping,和status是内置页面,不需要有真实文件存在于php-fpm的主机上,SCRIPT_FILENAME,只传递一个$fastcgi_script_name即可,即为status或ping
}
# 以上定义在一个虚拟主机配置段中,本例是在www.pc.com中
4,php-fpm配置
修改php-fpm配置文件,并开启status和ping的内置页面
[root@host3 php]# grep -v "^;" etc/php-fpm.conf |grep -Ev "^$"
[global]
[www]
user = nginx
group = nginx
listen = 9000
# php-fpm的进程用户,监听端口
listen.allowed_clients = 192.168.80.101,192.168.10.101
# 允许接入的客户端ip
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
# 进程相关不影响转发,保持默认即可
pm.status_path = /status
ping.path = /ping
ping.response = pong
# 定义status和ping页面
access.log = log/$pool.access.log
slowlog = log/$pool.log.slow
php_admin_value[error_log] = /var/log/fpm-php.www.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session
#日志相关,会话保存文件相关,不影响转发的配置
准备index.php文件
mkdir /data/php
vim /data/php/index.php
<?php
phpinfo()
?>
# 准备index.php文件
useradd nginx
chown -R nginx.nginx /data/php/
service php-fpmd restart
# 创建nginx用户,改目录权限,php-fpm的启动用户和nginx保持一致,否则会有权限问题;
# nginx和php-fpm两台主机的nginx用户,uid不必相同;但最好一致!
5,访问测试
报文头部加工
1、客户端请求报文
https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header
nginx透传客户端真实ip
1,使用proxy_set_header指令
server {
listen 80;
server_name www.pc.com;
root /data/nginx/pc;
index index.html;
location / {
proxy_set_header x-real-ip $remote_addr;
proxy_pass http://192.168.80.103;
}
}
# proxy_set_header指令,添加一个变量,值为引用的内建遍历$remote_addr
nginx -t
nginx -s reload
2,httpd修改日志格式
# 添加一个变量,和nginx定义的需保持一致;
LogFormat "%{x-real-ip}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" log1
# 引用上步定义的日志格式
CustomLog "logs/access_log" log1
# 语法检查,重启
httpd -t
httpd -k restart
3,访问,查看日志
[root@host1 ~]# curl www.pc.com
host4
# 查看httpd日志,比之前多了客户端的真实ip
# 100是客户端,101是nginx代理,103是httpd后端节点;
[root@host4 html]# tailf /var/log/httpd/access_log
192.168.80.101 - - [30/Aug/2020:13:46:09 +0800] "GET /path/1.html HTTP/1.0" 200 12 "-" "curl/7.29.0"
192.168.80.100 192.168.80.101 - - [30/Aug/2020:14:04:13 +0800] "GET / HTTP/1.0" 200 6 "-" "curl/7.29.0"
2、服务端响应报文
https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header
nginx对从后端接收到的报文头部,做增删修改,如加一个via字段,把自己nginx的ip加入,向客户端表示请求是经由自己转发;去掉后端服务的软件版本等信息;
1,利用add_header指令
server {
listen 80;
server_name www.pc.com;
root /data/nginx/pc;
index index.html;
location / {
proxy_set_header x-real-ip $remote_addr;
proxy_pass http://192.168.80.103;
add_header x-via $server_addr;
add_header x-accel $server_name;
}
}
2,访问,查看头部
[root@host1 ~]# curl -I www.pc.com
HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Sun, 30 Aug 2020 06:15:16 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 6
Connection: keep-alive
Last-Modified: Sun, 30 Aug 2020 04:47:06 GMT
ETag: "6-5ae10fa5ad668"
Accept-Ranges: bytes
# reload了nginx之后,头部多了2个字段;
[root@host1 ~]# curl -I www.pc.com
HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Sun, 30 Aug 2020 06:15:21 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 6
Connection: keep-alive
Last-Modified: Sun, 30 Aug 2020 04:47:06 GMT
ETag: "6-5ae10fa5ad668"
Accept-Ranges: bytes
x-via: 192.168.80.101 # nginx的ip
x-accel: www.pc.com # nginx哪个虚拟主机提供的转发