Nginx分布式框架详解80-85反向代理01

Nginx 如何变成一个代理服务器?Nginx 又如何将客户端的请求转发给其他的服务器?本内容将学习 Nginx 的反向代理知识。

反向代理概述

正向代理代理的对象是客户端,反向代理代理的对象是服务端,这是两者之间最大的区别。
nginx既可以实现正向代理,也可以实现反向代理。
我们先来通过一个小案例演示下 Nginx 正向代理的简单应用。

正向代理

  1. 服务端的设置
http {
    # 配置请求处理日志格式
    log_format main 'client send request Client-IP=$remote_addr ServerIP=$host';

    server {
        listen 80;
        server_name mayanan.cn;
        access_log logs/access.log main;
        location / {
            root html;
            index index.html;
        }
    }
}
  1. 使用客户端访问服务端:http://192.168.200.133,打开日志查看结果
    client send request Client-IP=114.245.203.80 ServerIP=mayanan.cn
  2. 代理服务器设置
server {
    listen 80;
    server_name flask-test.mayanan.cn;
    access_log logs/access.log main;
    location / {
        proxy_pass http://mayanan.cn;
    }
}
  1. 设置完成后,再次通过浏览器访问服务端
client send request Client-IP=123.57.142.92 ServerIP=mayanan.cn
client send request Client-IP=114.245.203.80 ServerIP=flask-test.mayanan.cn

通过对比,上下两次的日志记录,会发现虽然我们是客户端访问服务端,但是使用了代理,那么服务端能看到的只是代理发送过去的请求,这样就使用 Nginx 实现了正向代理的设置。
但是 Nginx 正向代理,在实际的应用中不是特别多,所以我们简单了解下,接下来我们继续学习 Nginx 的反向代理,这是 Nginx 比较重要的一个功能。

nginx反向代理之proxy_pass指令

反向代理语法配置

Nginx 反向代理模块的指令是由 ngx_http_proxy_module 模块进行解析,该模块在安装 Nginx 的时候已经自动加载到 Nginx 中了,接下来我们把反向代理中的常用指令一一介绍下:

  • proxy_pass: 配置代理的服务器地址
  • proxy_set_header: 转发给被代理服务器时,设置一些请求头信息
  • proxy_redirect: 防止客户端可以看到被代理服务器的地址
proxy_pass

该指令用来设置被代理服务器地址,可以是主机名称、IP 地址加端口号形式,没有默认值。

语法 默认值 位置
proxy_pass ; location

URL为要设置的被代理服务器地址,包含传输协议(http、https://)、主机名称或 IP 地址加端口号、URI 等要素。
例如:

# 例子
server {
    listen 80;
    server_name flask-test.mayanan.cn;
    access_log logs/access.log main;
    location /server {
        proxy_pass http://mayanan.cn;  // 不加斜线访问的是:http://mayanan.cn/server/index.html
    }
    location /server {
        proxy_pass http://mayanan.cn/;  // 加斜线访问的是:http://mayanan.cn/index.html
    }
}
在编写 proxy_pass 的时候,后面的值要不要加 /?

来看一个具体的例子来决定proxy_pass后面到底要不要加 /

server {
	listen 80;
	server_name localhost;
	location / {
        # 下面两个地址加不加斜杠,效果都一样,因为 location 后的 / 会添加在代理地址后面
		proxy_pass http://192.168.200.146;
		proxy_pass http://192.168.200.146/;
	}
}

server{
	listen 80;
	server_name localhost;
	location /server {
        # 下面两个地址必须加斜杠,因为 location 后的 /server 会添加在代理地址后面,第一个将没有 / 结尾
		#proxy_pass http://192.168.200.146;
		proxy_pass http://192.168.200.146/;
	}
}
# 上面的 location:当客户端访问 http://localhost/server/index.html
# 第一个 proxy_pass 就变成了 http://localhost/server/index.html
# 第二个 proxy_pass 就变成了 http://localhost/index.html 效果就不一样了。

第一个 location(第 4 行代码):当客户端访问 http://localhost/index.html,两个 proxy_pass 效果是一样的,因为 location 后的 / 会添加在代理地址后面,所以有没有 /,效果都一样。

第一个 location(第 14 行代码):当客户端访问 http://localhost/server/index.html,这个时候,第一个 proxy_pass 就变成了 http://192.168.200.146/server/index.html,第二个 proxy_pass 就变成了 http://192.168.200.146/index.html 效果就不一样了

如果不以 / 结尾,则 location 后的 /server 会添加在地址后面,所以第一个 proxy_pass 因为没有 / 结尾而被加上 /server,而第二个自带了 / ,所以不会添加 /server。

上面的例子仅仅针对:访问任意请求如 /server 时,想要代理到其他服务器的首页,则加 /,否则你如果真的想访问 /server 下的资源,那么不要加 /。

所以加了 / 后,请求的是服务器根目录下的资源。

反向代理之proxy_set_header指令

该指令可以更改 Nginx 服务器接收到的客户端请求的请求头信息,然后将新的请求头发送给代理的服务器。默认值是发送代理服务器的地址和 close。

语法 默认值 位置
proxy_set_header ; proxy_set_header Host $proxy_host; proxy_set_header Connection close; http、server、location

需要注意的是,如果想要看到结果,必须在被代理的服务器上来获取添加的头信息。
实例:

server {
            listen 80;
            server_name mayanan.cn;
            location / {
                default_type text/plain;
                return 200 $http_username;
            }
        }

        server {
            listen 80;
            server_name flask-test.mayanan.cn;
            charset utf-8;
            location /server {
                proxy_pass http://mayanan.cn/;
                proxy_set_header username TOM;
            }
        }

访问测试:http://flask-test.mayanan.cn/server/, 返回TOM
客户端访问的是服务器 A,服务器 A 会将请求转发给服务器 B,服务器 B 返回打印 TOM 的页面给服务器 A,服务器 A 最后返回给客户端。

反向代理之proxy_redirect指令

该指令是用来重置头信息中的『 Location 』和『 Refresh 』的值,防止客户端可以看到被代理服务器的地址。

因为客户端看到的返回结果是『 Location 』和『 Refresh 』的值,所以在到达代理服务器的时,将两个值修改掉,防止客户端直接看到被代理服务器的地址。

语法 默认值 位置
proxy_redirect redirect replacement;
proxy_redirect default;
proxy_redirect off; proxy_redirect default; http、server、location

为什么要用该指令
首先说明一下思路:客户端通过代理服务器 A 访问服务器 B 的资源,但是服务器 B 不存在该资源,则会报错。此时我们不希望它直接返回报错页面给客户端,我们希望服务器 B 返回的是它的欢迎页面。那么如何做呢?

首先在服务器 B 进行判断是否存在资源,不存在则返回自己的欢迎页面,即重定向到自己的欢迎页面地址并返回,此时浏览器的地址将会发生改变
代理服务器 A 收到服务器 B 的欢迎页面和地址,但是我们不能直接返回给客户端,因为它会暴露服务器 B 的地址,这是重定向的原因
此时用到 proxy_redirect 指令,重置服务器 B 返回过来的『 Location 』和『 Refresh 』值,将两个值改为代理服务器 A 的某个地址
因为改为了代理服务器 A 的某个地址,所以代理服务器 A 根据这个地址又去获取理服务器 B 的欢迎页面地址,返回给客户端
很绕,简单总结下:客户端通过 A 找 B 不存在的资源,B 不想返回报错页面,于是重定向到自己的欢迎页面地址并返回给 A,A 收到了页面和地址(正常情况不要接收地址,只接收页面),发现不能暴露 B 的地址,于是修改接收的 B 的地址为自己的某一个地址,这个地址会重新发送请求去获取 B 的欢迎页面地址,然后返回给客户端。

这里要明白 B 返回的是重定向后的欢迎页面,重定向后,浏览器地址栏会变成重定向的地址,所以 A 才会以自己的地址转发获取到 B 的地址,所以最后浏览器显示 A 的地址,看到的却是 B 的欢迎页面。

server {
    listen 80;
    server_name mayanan.cn;
    #access_log logs/access.log main;
    location / {
        root html;
        index index.html;
    }
    location /server {
        if (!-f $request_filename) {
            return 302 http://mayanan.cn;
        }
    }
}

server {
    listen 80;
    server_name flask-test.mayanan.cn;
    #access_log logs/access.log main;
    charset utf-8;
    location /server/abc {
        proxy_pass http://mayanan.cn;
        proxy_redirect http://mayanan.cn http://flask-test.mayanan.cn;
    }
}

修改完之后测试:

root@debian-01:/usr/local/nginx# curl -I http://flask-test.mayanan.cn/server/abc
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.22.0
Date: Sun, 04 Sep 2022 04:01:19 GMT
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: http://flask-test.mayanan.cn

该指令的三组选项

proxy_redirect redirect replacement;

redirect:被代理服务器返回的 Location 值
replacement:要替换 Location 的值
proxy_redirect default;

default:相比较第一组选项,default 仅仅提供了 redirect 和 replacement 的默认值

将本范围 location 块的 uri 变量作为 replacement。

将 proxy_pass 变量作为 redwadairect

server {
	listen  8081;
	server_name localhost;
	location /server { 
		proxy_pass http://192.168.200.146:8081/;
		proxy_redirect default;  # redirect 是 proxy_pass 的值:http://192.168.200.146:8081/
        						 # replacement 是 location 后的值:/server
        # 等价于:proxy_redirect http://192.168.200.146:8081/ /server
	}
}

proxy_redirect off;
关闭 proxy_redirect 的功能

反向代理的实战案例


服务器 1,2,3 存在两种情况

第一种情况: 三台服务器的内容不一样
第二种情况: 三台服务器的内容是一样

第一种情况
如果服务器 1、服务器 2 和服务器 3 的内容不一样,那我们可以根据用户请求来分发到不同的服务器。
服务器有限,只能以三个端口模拟三台服务器,实际上是一个 IP 对应一个服务器。
代理服务器配置文件内容:

server {
    listen 80;
    server_name mayanan.cn;
    location /server1 {
        proxy_pass http://flask-test.mayanan.cn/;
    }
    location /server2 {
        proxy_pass http://flask-demo.mayanan.cn/;
    }
}

服务器配置文件内容:

server {
    listen 80;
    server_name flask-test.mayanan.cn;
    default_type text/plain;
    return 200 'this is server1';
}
server {
    listen 80;
    server_name flask-demo.mayanan.cn;
    default_type text/plain;
    return 200 'this is server2';
}
posted @ 2022-09-04 15:42  专职  阅读(94)  评论(0编辑  收藏  举报