什么是反向代理?
反向代理(Reverse Proxy)是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给Internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
应用场景
代理通常用于在多个服务器之间分配负载,无缝显示来自不同网站的内容,或者通过HTTP之外的协议将处理请求传递给应用程序服务器。
当NGINX代理请求时,它会将请求发送到指定的代理服务器,获取响应并将其发送回客户端。
可以使用指定的协议将请求代理到HTTP服务器(另一个NGINX服务器或任何其他服务器)或非HTTP服务器(可以运行使用特定框架开发的应用程序,例如PHP或Python)。 支持的协议包括FastCGI,uwsgi,SCGI和memcached。
如何配置
要将请求传递给HTTP代理服务器,请在location内指定proxy_pass指令。 例如:
location /some/path/ { proxy_pass http://www.example.com/link/; }
此示例配置导致将在此location处理的所有请求传递到指定地址的代理服务器。该地址可以指定为域名或IP地址。 地址还可能包含一个端口。
请注意,在上面的第一个示例中,代理服务器的地址后跟URI/link/。如果URI与地址一起指定,则它将替换与location参数匹配的请求URI部分。
例如,此处带有/some/path/page.html URI的请求将代理到http://www.example.com/link/page.html。 如果指定的地址没有URI,或者无法确定要替换的URI部分,则传递完整的请求URI。
要将请求传递给非HTTP代理服务器,应使用相应的**_pass指令:
- fastcgi_pass将请求传递给FastCGI服务器
- uwsgi_pass将请求传递给uwsgi服务器
- scgi_pass 将请求传递给SCGI服务器
- memcached_pass将请求传递给FastCGI服务器
proxy_pass指令也可以指向服务器的命名组。 在这种情况下,根据指定的方法在组中的服务器之间分配请求。
传递请求头部
默认情况下,NGINX在代理请求中重新定义两个header字段“Host”和“Connection”,并删除其值为空字符串的header字段。 “Host”设置为$ proxy_host变量,“Connection”设置为close。
要更改这些设置,以及修改其他header字段,请使用proxy_set_header指令。
可以在某个location或更高位置指定此指令。它也可以在特定的server 上下文或 http 块中指定。
例如:
location /some/path/ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://localhost:8000; }
在此配置中,“Host”字段设置为$host变量。
为了防止header字段被传递到代理服务器,将其设置为空字符串,如下所示:
location /some/path/ { proxy_set_header Accept-Encoding “”; proxy_pass http://localhost:8000; }
配置缓冲
默认情况下,NGINX缓冲来自代理服务器的响应。响应存储在内部缓冲区中,直到接收到整个响应后才发送给客户端。
缓冲有助于优化慢客户端的性能,如果响应从NGINX同步传递到客户端,则会浪费代理服务器时间。但是,当启用缓冲时,NGINX允许代理服务器快速处理响应,而NGINX将响应存储的时间与客户端下载它们所需的时间相同。
负责启用和禁用缓冲的指令是proxy_buffering。默认情况下,它设置为on并启用缓冲。
proxy_buffers指令控制为请求分配的缓冲区的大小和数量。来自代理服务器的响应的第一部分存储在单独的缓冲区中,其大小使用proxy_buffer_size指令设置。这部分通常包含一个相对较小的响应头,可以使其小于响应其余部分的缓冲区。
在以下示例中,增加了默认缓冲区数,并使响应第一部分的缓冲区大小小于默认值。
location /some/path/ { proxy_buffering off; proxy_pass http://localhost:8000; }
如果禁用缓冲,则响应将在从代理服务器接收响应时同步发送到客户端。对于需要尽快开始接收响应的快速交互式客户端,此行为可能是理想的。
要在特定位置禁用缓冲,使用off参数将proxy_buffering指令放置在location 中,如下所示:
location /some/path/ { proxy_buffering off; proxy_pass http://localhost:8000; }
在这种情况下,NGINX仅使用proxy_buffer_size配置的缓冲区来存储响应的当前部分
如果代理服务器具有多个网络接口,有时您可能需要选择特定的源IP地址以连接到代理服务器或上游服务器。
如果将NGINX之后的代理服务器配置为接受来自特定IP网络或IP地址范围的连接,这可能很有用。
指定proxy_bind指令和必要的网络接口的IP地址:
location /app1/ {
proxy_bind 127.0.0.1;
proxy_pass http://example.com/app1/;
}
location /app2/ {
proxy_bind 127.0.0.2;
proxy_pass http://example.com/app2/;
}
IP地址也可以用变量指定。例如,$server_addr变量传递接受请求的网络接口的IP地址:
location /app3/ {
proxy_bind $server_addr;
proxy_pass http://example.com/app3/;
}
开始案例
front配置
server {
listen 80;
server_name test.front.com;
access_log /var/log/front_access.log;
error_log /var/log/front_error.log;
location /back1/api/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://test.back1.com:8081/api/;
}
location /back2 {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://test.back2.com:8082/;
}
location /back3 {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://test.back3.com:8083;
}
}
back1 back2 back3配置基本相同,只要把配置文件中的back1改为back2或者back3,以及把8081端口改为8082,8083就可以了。
server { listen 8081; server_name test.back1.com; index index.html index.htm index.php; root /www/back1; location / { try_files $uri @rewriteapp; } location @rewriteapp { rewrite ^(.*)$ /index.php/$1 last; } access_log /var/log/back1_access.log; error_log /var/log/back1_error.log; location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|mp3|swf|xlsx)$ { expires 1M; access_log off; add_header Cache-Control “public”; } location ~* \.(?:css|js|swf|xlsx)$ { expires 1y; access_log off; add_header Cache-Control “public”; } location ~ ^/.*\.php(/|$) { fastcgi_pass 127.0.0.1:9000; fastcgi_split_path_info ^(.+\.php)(/.*)$; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
然后我们在本地的/etc/host里面加上四个域名
127.0.0.1 test.front.com
127.0.0.1 test.back1.com
127.0.0.1 test.back2.com
127.0.0.1 test.back3.com
然后重启一下nginx。
接着我们在back1,back2,back3下面都创建一个index.php
$ cat index.php
<?php
echo 'server_name=' . ($_SERVER['SERVER_NAME']) . PHP_EOL;
echo 'request_uri=' . ($_SERVER['REQUEST_URI']);
然后我们访问一下
大家可能看到了,三个访问显示的request_uri都不一样,那我们再看一眼我们的配置文件
我们可以看到第一个location,这个的配置的意思是说将对应链接的参数中的/back1/api/替换为api/ http://test.front.com/back1/api/get/goods/100 参数为/back1/api/get/goods/100替换一下就成了/api/get/goods/100
第二个location的意思是指将/back2替换成/。http://test.front.com/back2/api/get/goods/100参数为/back2/api/get/goods/100 替换为/ 那就是//api/get/goods/100
第三个location的意思是不做任何替换,直接将对应链接的参数全部拿过来,那就是/back3/api/get/goods/100
注意:
我们有时候配置代理服务器的时候一定要注意proxy_pass后面的/。像后面的back3情况,很可能/back3/api/get/goods/100是请求失败的,正确的请求应该是/api/get/goods/100。
参考链接:
https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/#intro
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header