欢迎大家关注微信公众号后端开发杂谈, 这里有更多实用的干货等着你来拿!
简介: 本文去认识 nginx 的正向代理和反向代理, 以及如何去配置这些代理
resolver指令
用于指定DNS服务器的IP地址. DNS服务器主要工作是进行域名解析, 将域名映射为对应的IP地址. 语法结构如下:
resolver ADDRESS ... [valid=TIME];
ADDRESS, DNS服务器的IP地址. 如果不指定端口号, 默认使用53端口号.
TIME, 设置数据包在网路中的有效时间. 出现该指令定主要原因是, 在访问站点的时, 有很多情况下使得数据包在一定时间内不能被传递到目的地, 但是又不能让该数据包无限期的存在, 于是就需要设定一段时间, 当数据包在这段时间内没有到达目的地, 就会被丢弃, 然后发生者会接收到一个消息, 并决定是否要重发该数据包.
例子:
resolver 127.0.0.1 [::1]:5353 valid=30s;
resolver_timeout指令
用于设置DNS服务器域名解析超时时间.
resolver_timeout TIME;
proxy_pass指令
用于设置代理服务器的协议和地址, 它不仅仅用于nginx服务器的代理服务, 更主要的是用于反向代理服务
proxy_pass URL;
URL, 即为设置的代理服务器协议和地址
.
在代理服务器配置当中, 该指令的设置相对固定.
proxy_pass http://$http_host$request_uri;
其中, 代理服务器协议设置为HTTP, h t t p h o s t 和 http_host和 httphost和request_uri两个变量是NGINX配置支持的用于自动获取主机和URI的变量.
server {
resolver 8.8.8.8;
listen 80;
location / {
proxy_pass http://$http_host$request_uri;
}
}
proxy_pass指令
用来设置被代理服务器的地址. 可以是主机名,IP地址加端口号等形式.
proxy_pass URL;
该指令可以在location, if in location, limit_except 中进行配置.
设置后端服务器的协议和地址, 还可以设置可选的URI以定义本地路径和后端服务器的映射关系. 可以设置的协议是"http"或"https". 而地址既可以使用域名或者IP地址加端口号(可选)的形式来定义:
proxy_pass http://localhost:8080/uri/;
又可以使用UNIX域套接字路径来定义. 该路径接在"unix"字符串后面, 两端由冒号(:)所包围:
proxy_pass http://unix:/tmp/bacend.socket:/uri/;
如果解析一个域名得到多个地址, 所有的地址都会以轮询的方式被使用.
- 如果 proxy_pass 使用了 URI, 当请求到后端服务器时, “规范化以后的请求路径"与"配置中的路径"的匹配部分将被替换为” 指令中定义的URI":
location /api/ { proxy_pass http://127.0.0.1/remote/; }
言外之意, 如果客户端到nginx请求uri是 “/api/name”, 那么到后端服务器的uri将变成"/remote/name", 其中"/api/“是
规范化的请求路径和配置中的路径的相同部分, 被指令中定义的URI(”/remote/")替换. 也就是说, 配置中的路径和指令中定义的
URI在格式上需要保持一致.
- 如果 proxy_pass 没有使用 URI, 到后端服务器的请求URI一般是客户端发起的原始URI, 如果nginx改变了请求URI, 则到后端服务器的URI是nginx改变以后完整的规范化URI:
location /api/ { proxy_pass http://127.0.0.1; }
使用正则表达式定义路径. 这种状况下, 指令不应该使用URI
在需要代理的路径中, 使用
rewrite
指令改变了URI, 但仍使用相同配置处理请求(break), 在这种状况下, 本指令设置的URI 会被忽略, 改变后的URI将被发送给后端服务器.location /api/ { rewrite /api/([^/]+) /users?name=$1 break; proxy_pass http://127.0.0.1; }
言外之意, 如果客户端到nginx请求uri是 “/api/zhangsan”, 那么到后端服务器的uri将变成"/users?name=zhangsan".
break
表示终止当前server的匹配,那么最终会执行proxy_pass
.
server {
listen 80;
server_name www.baidu.com;
location /server/ {
proxy_pass http://192.168.1.1;
}
}
如果客户端使用 http://www.baidu.com/server
发起请求, 由于proxy_pass指令的不包含URI, 到后端服务器的地址是http://192.168.1.1/server
.
server {
listen 80;
server_name www.baidu.com;
location /server/ {
proxy_pass http://192.168.1.1/local/;
}
}
如果客户端使用 http://www.baidu.com/server
发起请求, 由于proxy_pass指令的包含URI, 到后端服务器的地址是 http://192.168.1.1/local/
.
proxy_pass_request_headers指令
用于配置是否将 原始请求的Header
发送给上游服务器.
proxy_pass_request_headers on|off;
默认是开启(on), 该指令可以在http块, server块,或者location块中进行配置.
允许在传递给 上游服务器
的请求头当中重新定义或添加字段. 该值可以包含文本, 变量, 及其组合. 当且仅当 当前级别上未定义
proxy_set_header
指令时,这些指令才从上一级继承
. 默认情况下, 仅重新定义两个字段:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
如果启用了缓存, 则会从原始请求Header当中的 “If-Modified-Since”, “If-Unmodified-Since”, “If-None-Match”, “If-Match”, “Range”, 和 “If-Range” 不会传递到代理服务器.
proxy_set_header FIELD VALUE;
FIELD, 要修改的头域.
VALUE, 更改的值, 支持使用文本, 变量或者变量的组合.
例子:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header
和 add_header
的区别:
proxy_set_header
是 nginx 设置请求头
信息给上游服务器, add_header
是nginx设置 响应头
信息给客户端.
默认情况下, nginx不会将 上游服务器
的响应中的标头字段 “Date”, “Server”, “X-Pad” 和 “X-Accel-…” 传递给客户端.
proxy_hide_header
指令 设置了不会传递的其他字段
. 相反, 如果需要允许传递上面的字段, 则可以使用proxy_pass_header
指令.
言外之意是
proxy_pass_header
的值只能是 “Date”, “Server”, “X-Pad” 和 “X-Accel-…” 当中一个.
prox_pass_header FIELD;
proxy_hide_header FIELD;
FIELD是需要发送的头域.
该指令可以在http块, server块,或者location块中进行配置.
proxy_ignore_headers指令
设置不处理 上游服务器
返回的指定响应头.
proxy_ignore_headers FIELD ...;
FIELD是要设置的HTTP响应头的头域. 可选的值包含: “X-Accel-Redirect”, “X-Accel-Expires”, “X-Accel-Limit-Rate” “X-Accel-Buffering”, “X-Accel-Charset”, “Expires”, “Cache-Control”, “Set-Cookie”, “Vary”.
如果不被取消, 这些头部的处理可能产生下面的结果:
上述的header之间关系:
请求路径:
客户端 -> nginx -> 上游服务器
执行顺序如下:
proxy_pass_request_headers (nginx->上游服务器, 客户端的请求头是否发送)
proxy_set_header (nginx->上游服务器, 修改请求的头)
响应路径:
上游服务器 -> nginx -> 客户端
proxy_pass_header (上游服务器->nginx, nginx可以允许的响应头, 可选数量比较少)
proxy_hide_header (上游服务器->nginx, nginx可以隐藏的响应头)
proxy_ignore_headers (上游服务器->nginx, 可以忽略的响应头, 可选数量比较少)
proxy_pass_request_body指令
用于配置是否将客户端的请求体
发送给上游服务器.
proxy_pass_request_body on|off;
默认是开启(on).
该指令可以在http块, server块,或者location块中进行配置.
proxy_set_body指令**用于更改nginx服务器接收到的**客户端请求的请求体
, 然后将新的请求体发送给上游服务器.
proxy_set_body VALUE;
VALUE, 更改的信息, 支持使用文本, 变量或者变量的组合.
proxy_connect_timeout指令
配置nginx服务器到上游服务器建立连接的超时时间. 默认是60s.
proxy_read_timeout指令
配置nginx服务器从上游服务器读取响应的超时, 此超时是之相邻两次读操作之间是最长时间间隔, 而不是整个响应传输完成的最长时间. 如果上游服务器在超时时间段内没有传输任何数据, 连接将被关闭. 默认是60s.
proxy_send_timeout指令
配置nginx向上游服务器传输请求的超时. 此超时是之相邻两次写操作之间是最长时间间隔, 而不是整个请求传输完成的最长时间. 如果上游服务器在超时时间段内没有接收到任何数据, 连接将被关闭. 默认是60s.
proxy_http_version指令
设置nginx服务器提供代理服务器的HTTP协议版本. 默认是1.0, 1.1版本支持服务器组中的keepalive指令.
proxy_method指令
用于设置nginx服务器请求被代理服务器时使用的方法, 一般是POST或者GET. 设置了该指令, 客户端的请求方法将被忽略.
proxy_method METHOD;
proxy_ignore_client_abort指令
用于设置在客户端中断请求时, nginx服务器是否中断对上游服务器的请求.
proxy_ignore_client_abort on|off;
默认是off. 即当客户端中断网络请求时, nginx服务器中断对上游服务器的请求.
proxy_redirect REDIRECT REPLACE;
proxy_redirect default;
proxy_redirect off;
REDIRECT匹配Location头域值的字符串, 支持变量使用和正则表达式
.
REPLACE用于替换REDIRECT变量内容的字符串, 支持变量的使用
.
作用于 http, server, location
proxy_redirect指令
设置后端服务器"Location"响应头和"Refresh"响应头的替换文本. 假设上游服务器返回的响应头是:
Location: http://localhost:8080/two/some/uri/
那么, 指令 proxy_redirect http://localhost:8080/two http://frontend/one/;
将把 “Location” 改写为:
Location: http//frontend/one/some/uri/
REPLACE
字符串可以省略服务器名, 即指令等价为 proxy_redirect http://localhost:8080/two /one/
使用 default
, 代表使用 location块
的uri变量作为REPLACE, 并使用 proxy_pass
的uri作为REDIRECT下面的两个配置是等价的:
location /one/ {
proxy_pass http://upstream:port/two/;
proxy_redirect default;
}
location /one/ {
proxy_pass http://upstream:port/two/;
proxy_redirect http://upstream:port/two/; /one/;
}
上面的配置两者是一致的.
因为同样的原因, proxy_pass
指令使用变量事, 不允许 proxy_redirect
使用 default
参数.
除此之外, 可以同时定义多个 proxy_redirect
指令:
proxy_redirect default;
proxy_redirect http://localhost:8080/ /;
proxy_redirect http://www.example.com/ /;
另外, off
参数可以使所有相同配置级别的 proxy_redirect
指令无效:
proxy_redirect off;
proxy_redirect default;
proxy_redirect http://localhost:8080/ /;
proxy_redirect http://www.example.com/ /;
proxy_cookie_domain off;
proxy_cookie_domain DOMAIN REPLACE;
proxy_cookie_domain
设置 Set-Cookie
响应头的 domain
属性的替换文本. 假设上游服务器返回的 “Set-Cookie” 响应头包含有属性 “domain=localhost”, 那么指令 proxy_cookie_domain localhost example.org
将改变这个属性改为 “domain=example.org”.
DOMAIN 和 REPLACE 配置字符串, 以及 domain
属性中起始的点将被忽略. 匹配过程大小写不敏感.
DOMAIN 和 REPLACE 配置字符串可以包含变量:
proxy_cookie_domain www.$host $host;
DOMAIN 和 REPLACE 配置字符串可以使用正则表达式. 这事 DOMAIN 应以 “~” 标志开头, 且可以使用命名匹配组和位置匹配组, 而且 REPLACE 可以引用这些匹配组:
proxy_cookie_domain www.$host $host;
proxy_cookie_domain ~\.([a-z]+\.[a-z]+)$ $1;
off
参数可以取消当前配置级别的所有 proxy_cookie_domain
指令.
proxy_cookie_domain off;
proxy_cookie_domain www.$host $host;
proxy_cookie_domain ~\.([a-z]+\.[a-z]+)$ $1;
proxy_cookie_path off;
proxy_cookie_path PATH REPLACE;
用法和
proxy_cookie_domain
类似.
proxy_intercept_errors on|off;
当 上游服务器
的响应状态码大于等于 400, 决定是否直接将响应发送给客户达. 亦或将响应转发给nginx由 err_page
指令来处理.
proxy_next_upstream STATUS ...;
STATUS是设置的上游服务器返回的状态, 可以是一个或者多个, 这些状态包括:
指定在何种状况下一个失败的请求应该被发送到下一台上游服务器.
proxy_ssl_session_reuse指令
配置是否使用基于SSL安全协议的会话连接(https)被代理的服务器.
proxy_ssl_session_reuse on|off;
默认设置为开启(on)状态. 如果在错误日志中发生"SSL3_GET_FINSHED:digest check failed"的状况, 可以将该指令配置为关闭(off)状态.