nginx之七层代理

nginx之七层代理

七层代理

​ 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

见nginx编译安装部分

2,编辑php

见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,访问测试

image-20200830152200712

image-20200830152147282

image-20200830152134015

报文头部加工

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哪个虚拟主机提供的转发
updatedupdated2020-10-192020-10-19
加载评论