NGINX的重写与反向代理机制解析

目录

引言

一、重写功能

(一)if指令

1.判断访问使用的协议

2.判断文件

(二)return指令

1.设置返回状态码

2.返回指定内容

3.指定URL

(三)set指令

1.手动输入变量值

2.调用其它变量值为自定义变量

(四)break指令

(五)rewrite指令

1.permanent(永久重定向301)

2.redirect(临时重定向302)

3.break

4.last

(六)防盗链

1.实现盗链

2.实现防盗链

二、反向代理

(一)实现代理

(二)针对一个URL进行代理

(三)动静分离

(四)反向代理缓存

[(五)反向代理客户端 IP 透传](#(五)反向代理客户端 IP 透传)

1.单机代理透传

2.多机代理透传

(六)反向代理负载均衡

1.Nginx负载均衡策略

①.轮询

②.加权轮询

③hash

2.状态参数


引言

在现代Web架构中,NGINX以其高性能、稳定性和灵活性而广受青睐。本文将深入探讨NGINX中的两个核心功能:URL重写和反向代理,以帮助您更好地理解和配置这些强大的特性。

一、重写功能

在Nginx中,重写(rewriting)功能主要用于改变请求的URI,以实现URL美化、路径映射、SEO优化等目的。这主要通过 rewrite 指令来完成

Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求,此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库,rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能,比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为自动访问,另外还可以在一定程度上提高网站的安全性。

例如在上文的https功能中,比如客户去访问京东或者淘宝,在不开启重写功能的清空下,如果直接输入www.toabao.com去访问网址,会通过http协议去访问网址(http://www.taobao.com),它会提示这是一个不安全的网址,这样会使访问者担心网址的安全性,从而放弃访问。所以会开启重写功能,通过修改URL去使用https去访问(https://www.taobao.com

官方文档: Module ngx_http_rewrite_module

(一)if指令

用于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进行配置,Nginx的if语法仅能使用if做单次判断,不支持使用if else或者if elif这样的多重判断

官方文档:[Module ngx_http_rewrite_module](#Module ngx_http_rewrite_module)

其基本用法为:

if (条件匹配) {

执行语句

}

使用正则表达式对变量进行匹配,匹配成功时if指令认为条件为true,否则认为false,变量与表达式之间使用以下符号链接

|--------|------------------------------------------|
| = | 比较变量和字符串是否相等,相等时if指令认为该条件为true,反之为false |
| != | 比较变量和字符串是否不相等,不相等时if指令认为条件为true,反之为false |
| ~ | 区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假 |
| !~ | 区分大小写字符,判断是否匹配,不满足匹配条件为真,满足匹配条件为假 |
| ~* | 不区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假 |
| !~* | 不区分大小字符,判断是否匹配,满足匹配条件为假,不满足匹配条件为真 |
| -f和!-f | 判断请求的文件是否存在和是否不存在 |
| -d和!-d | 判断请求的目录是否存在和是否不存在 |
| -x和!-x | 判断文件是否可执行和是否不可执行 |
| -e和!-e | 判断请求的文件或目录是否存在和是否不存在(包括文件,目录,软链接) |

如果$变量的值为空字符串或0,则if指令认为该条件为false,其他条件为true。

nginx 1.0.1之前$变量的值如果以0开头的任意字符串会返回false

1.判断访问使用的协议

使用其它客户端进行访问

2.判断文件

判断文件是否存在或不存在

$request_filename:访问文件的绝对路径

使用客户端进行访问

(二)return指令

return用于完成对请求的处理,并直接向客户端返回响应状态码,比如:可以指定重定向URL(对于特殊重定向状态码,301/302等) 或者是指定提示文本内容(对于特殊状态码403/500等),处于此指令后的所有配置都将不被执行,return可以在server、if 和 location块进行配置

官方文档:[Module ngx_http_rewrite_module](#Module ngx_http_rewrite_module)

cs 复制代码
return code; 
#返回给客户端指定的HTTP状态码

return code [text]; 
#返回给客户端的状态码及响应报文的实体内容,可以调用变量,其中text如果有空格,需要用单或双引号

return code url; 
#返回给客户端的URL地址

1.设置返回状态码

当访问一个文件不存在时,正常的状态码为404,可以通过配置去修改返回的状态码

使用客户端进行访问

2.返回指定内容

return code [text];

返回给客户端的状态码及响应报文的实体内容,可以调用变量,其中text如果有空格,需要用单或双引号

使用客户端访问

curl是文字版的浏览器可以看到指定的信息,但是图形版浏览器不可以

需要使用default_type定义文本格式

3.指定URL

当用户访问到一个不存在的文件时,可以通过return指定状态码,并重定向到新指定的URL下

修改配置文件,并创建指定的URL

使用客户端访问不存在的文件时,就会跳转到主页面

可以看到,两次访问的结果并不一样

第一次执行命令:curl 192.168.83.40/xxx

这个命令没有添加任何参数来处理服务器返回的HTTP重定向响应。在配置中设置了将 /xxx 路径重定向到另一个URL。因此,curl 只显示了服务器发送的302 Found响应的内容,而没有自动跟随重定向到新的URL。

第二次执行命令:curl 192.168.83.40/xxx -L

这次执行时添加了 -L 参数,它告诉 curl 在接收到服务器返回的重定向响应时自动跟随并获取最终的目标页面内容。所以这次您看到了 "welcome to nginx",这是重定向目标页面的实际内容。

也可以跳转到其它网址

使用谷歌浏览器访问不存在的页面时,确实可以跳转到指定的URL,但是状态码却不是301

而是307

307:表示临时重定向

因为浏览器会自行缓存,而访问的是不存在的文件,并不会对该URL进行永久缓存

可以修改一下配置文件,通过访问存在的页面,跳转到百度

因为URL是真实存在的文件,所以会永久缓存

(三)set指令

指令用于设置变量的值。这些变量可以在后续的配置块或指令中使用

官方文档:Module ngx_http_rewrite_module

1.手动输入变量值

使用客户端访问不存在的文件时,就会输出变量内容

2.调用其它变量值为自定义变量

也可以通过调用其它变量值,定义为自己设置的变量的值

使用客户端访问/ip

(四)break指令

用于中断当前相同作用域(location)中的其他Nginx配置,与该指令处于同一作用域的Nginx配置中,位于它前面的配置生效,位于后面的 ngx_http_rewrite_module 模块中指令(set、if等)就不再执行,Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,该指令可以在server块和location、if块中使用

官方文档:Module ngx_http_rewrite_module

使用客户端访问测试

使用客户端访问时,只能看到break以上的 ngx_http_rewrite_module 模块指令

(五)rewrite指令

通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配,rewrite主要是针对用户请求的URL或者是URI做具体处理

官方文档:Module ngx_http_rewrite_module

其语句块写法为:

rewrite 原始访问URL 实际访问的URL 标志[premanent(301) redirect(302) break、last]

正则匹配格式为:

cs 复制代码
. #匹配除换行符以外的任意字符
\w #匹配字母或数字或下划线或汉字
\s #匹配任意的空白符
\d #匹配数字    [0-9]   
\b #匹配单词的开始或结束
^ #匹配字付串的开始
$ #匹配字符串的结束
* #匹配重复零次或更多次
+ #匹配重复一次或更多次
? #匹配重复零次或一次
(n) #匹配重复n次
{n,} #匹配重复n次或更多次
{n,m} #匹配重复n到m次
*? #匹配重复任意次,但尽可能少重复
+? #匹配重复1次或更多次,但尽可能少重复
?? #匹配重复0次或1次,但尽可能少重复
{n,m}? #匹配重复n到m次,但尽可能少重复
{n,}? #匹配重复n次以上,但尽可能少重复
\W  #匹配任意不是字母,数字,下划线,汉字的字符
\S #匹配任意不是空白符的字符
\D #匹配任意非数字的字符
\B #匹配不是单词开头或结束的位置
[^x] #匹配除了x以外的任意字符
[^kgc] #匹配除了kgc 这几个字母以外的任意字符

注意:如果在同一级配置块中存在多个rewrite规则,那么会自下而下逐个检查;被某条件规则替换完成后,会重新一轮的替换检查,隐含有循环机制,但不超过10次;如果超过,提示500响应码,标志位用于控制此循环机制如果替换后的URL是以http://或https://开头,则替换结果会直接以重定向返回给客户端, 即永久重定向 301

rewrite 标志位 使用介绍

利用nginx的rewrite的指令,可以实现url的重新跳转,rewrtie有四种不同的flag,分别是redirect(临时重定向302)、permanent(永久重定向301)、break和last。其中前两种是跳转型的flag,后两种是代理型

1.permanent(永久重定向301)

cs 复制代码
server {
  listen 80;
  server_name www.china.com;
  root /data/html;
location /computer {
rewrite ^/computer/(.*)  /pc/$1 permanent;
#客户端请求以 /computer 开头并且后面跟随任意内容(通过 (.*) 正则表达式捕获)
#Nginx会使用rewrite指令将原始请求路径重写:/pc/$1(后向引用)也就是(.*)的内容
#permanent表示状态码为301
}
}
mkdir /data/html/pc
#创建指定URL
echo  "welcome to txt" > /data/html/pc/txt
#创建数据文件,并添加内容

使用客户端访问时,访问的绝对路径为/data/html/computer/(.*)

这样做的目的是永久性地将 /computer 下的所有资源映射到 /pc 相应的路径下,以便进行URL结
构的调整或优化搜索引擎收录等目的。

可以使用-vL查看跳转的详细信息

分析一下为什么需要加-L,查看不加-L的信息

可以看到,不加-L只得知状态码及新的URL,并没有跟随重定向跳转,所以需要加上-L跟随重定向

2.redirect(临时重定向302)

临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求

redirect会返回状态码为302

permanent(永久重定向301)、redirect(临时重定向302)的区别

永久重定向的,当nginx服务关闭后,它会从浏览器的缓存记录中打开缓存的URL;而临时重定向的关闭服务后无法进行访问

当状态码为301时

curl是模拟浏览器,无法看到具体信息,可以使用谷歌浏览器的F12,查看信息。而谷歌浏览器因为文件类型限制原因,无法直接打开txt,需要将txt文件该命为以.txt结尾或.html结尾的等其它类型文件

mv /data/html/pc/txt /data/html/pc/1.txt

此时关闭nginx服务,依然可以访问到

如果状态码为302,只是临时缓存,当服务关闭后就无法访问

关闭服务后再次访问就会访问失败

3.break

重写完成后,停止对当前URL在当前location中后续的其它重写操作,而后直接跳转至重写规则配置(如return、set)块之后的其它配置;结束循环

使用客户端访问

当用户访问/data/html/computer/txt文件时,会正则匹配到第11行的内容,从而重定向URL到/data/html/pc/txt

4.last

重写完成后,停止对当前URI在当前location中后续的其它重写操作,而后对新的URL启动新一轮重写检查,不建议在location中使用

适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户301

根据配置,在用户访问的时候,重定向后结束return 302;的指令,而后根据新的URL(/data/html/pc/txtx)匹配下面的location去执行新的location语句块中的指令返回301状态码

当新的URL匹配不到任何语句块时,则会直接访问该URL

last与break的区别

last: 当使用 last 标志时,Nginx会停止当前location块内剩余的所有 rewrite 规则,并重新开始寻找与新的URI匹配的location块。这意味着Nginx会继续检查配置文件中的其他location块以找到一个最适合处理已重写请求的location。 如果没有找到其他匹配的location,Nginx将使用最接近原始请求URI的location块来处理请求。

break: 使用 break 标志时,Nginx同样会停止当前location块内剩余的所有 rewrite 规则,但是它不会重新查找新的location块进行匹配。相反,它会在当前location块内继续执行后续的配置指令(如 proxy_pass、echo 等),或者直接返回响应给客户端。

实战:

使用重写功能将HTTP协议转换成HTTPS协议访问

输入http://192.168.83.40进行访问

(六)防盗链

防盗链基于客户端携带的referer实现,referer是记录打开一个页面之前记录是从哪个页面跳转过来的标记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗链,referer就是之前的那个网站域名,正常的referer信息有以下几种:

cs 复制代码
none
#请求报文首部没有referer首部,比如用户直接在浏览器输入域名访问web网站,就没有referer信息。
blocked
#请求报文有referer首部,但无有效值,比如为空。
server_names
#referer首部中包含本主机名及即nginx 监听的server_name。
arbitrary_string
#自定义指定字符串,但可使用*作通配符。示例: *.kgc.org www.kgc.*
regular expression
#被指定的正则表达式模式匹配到的字符串,要使用~开头,例如:~.*\.kgc\.com

1.实现盗链

使用两台机器,两个机器同时开启http服务(nginx、httpd均可)

通过pc1去访问pc2的图片,且留在pc1的页面

首先在pc2的主站点目录上建一个文件

在pc1的web服务的主站点目录上建立index.html文件,并输入以下内容

cs 复制代码
这段HTML代码定义了一个简单的网页结构,当在浏览器中打开时,会显示以下内容:

页面标题(Heading 1)显示文本 "this is 192.168.83.100",

页面中嵌入了一张图片,其 src 属性设置为 "http://192.168.83.40/nginx.jpg"。
这意味着浏览器将尝试从 192.168.83.40 这个服务器上的 /nginx.jpg 路径加载并显示一张图片

开启pc1的http服务

使用真机去访问pc1(192.168.83.100),就会显示pc2(192.168.83.40)web服务主站点目录下的nginx.jpg文件

也可以通过域名实现访问

在192.168.83.100的web服务配置文件中添加域名解析

在pc2的配置文件中,添加server_name www.china.com;而后重新加载配置文件

在主机的C:\Windows\System32\drivers\etc/hosts文件中添加域名解析

解析pc1的主机

这个时候就可以使用域名进行访问了

2.实现防盗链

在pc2的web服务配置文件中添加配置信息

cs 复制代码
location ~* \.(jpg|gif|swf|jpeg|bmp)$ {
#匹配所有以.jpg、.gif、.swf、.jpeg和.bmp结尾的URL路径。
valid_referers none blocked *.china.com china.com;
#设置了有效的referer来源列表,允许以下几种情况:
#none:表示没有referer(直接访问或通过链接工具打开)。
#blocked:表示referer被浏览器阻止了。
#*.china.com:表示所有以 .china.com 结尾的域名下的referer都是有效的。
#china.com:表示 china.com 主域名本身的referer也是有效的
if ( $invalid_referer ){
#如果请求的referer不在有效referer列表内,则 $invalid_referer 变量会被设置为真
return 403;
#返回HTTP状态码403

再去使用浏览器访问时,就会拒绝访问该文件

使用允许的域名可以访问到

二、反向代理

反向代理:reverse proxy,指的是代理外网用户的请求到内部的指定的服务器,并将数据返回给用户的一种方式,这是用的比较多的一种方式

Nginx 除了可以在企业提供高性能的web服务之外,另外还可以将 nginx 本身不具备的请求通过某种预定义的协议转发至其它服务器处理,不同的协议就是Nginx服务器与其他服务器进行通信的一种规范,主要在不同的场景使用以下模块实现不同的功能

ngx_http_proxy_module: 这个模块实现了HTTP反向代理功能。它允许Nginx接收客户端的HTTP请求,并将请求转发到上游服务器(如应用服务器),同时将上游服务器的响应返回给客户端。通过此模块,可以实现负载均衡、缓存等功能。

代理原理有两种

同构代理:

  • 当Nginx作为代理服务器时,如果其后端服务采用的是相同的技术栈、协议或者数据格式,我们可以称这些后端为"同构"。例如,所有的后端都是基于HTTP/HTTPS协议提供RESTful API服务,并且返回的数据格式(如JSON)也一致。在这种情况下,Nginx只需要根据配置文件中的规则将请求转发到合适的后端服务器即可,无需对请求或响应内容做过多的转换处理。

异构代理:

  • 而在异构环境中,Nginx后面的后端服务可能采用了不同的技术栈、协议或者数据格式。比如一部分是HTTP REST API,另一部分是PHP Python等服务,或者是不同版本的同一服务接口。此时,Nginx不仅需要正确地路由请求,还可能需要进行额外的协议转换、负载均衡策略调整等复杂操作来适应不同后端的需求

ngx_http_upstream_module: 这个模块与ngx_http_proxy_module紧密相关,用于定义一组后端服务器(upstream)作为代理的目标。它可以配置负载均衡算法,健康检查等高级功能,以确保对后端服务器的高效和可靠访问。

ngx_stream_proxy_module : 这个模块提供了TCP/UDP协议层面上的代理服务,适用于非HTTP协议的应用场景,例如SMTP、IMAP、MySQL等基于TCP或UDP的服务。ngx_http_fastcgi_module: Nginx中的FastCGI代理模块,用于处理PHP、Python等动态语言生成的内容。当接收到需要执行FastCGI程序的请求时,此模块会将请求传递给FastCGI服务器(如PHP-FPM),并将执行结果返回给客户端

ngx_http_uwsgi_module: 类似于ngx_http_fastcgi_module,这个模块用于处理使用uWSGI协议的应用,通常用于Python(尤其是Django和Flask框架)应用程序的部署。该模块将HTTP请求转换为uWSGI协议格式并发送到支持uWSGI协议的后端应用服务器。

官方文档: Module ngx_http_proxy_module

最简单的理解方式就是客户访问web服务,通过代理服务器获取web服务的数据信息

也可以设置多个代理服务器,主从服务,防止代理服务器挂了之后,导致整个服务崩坏

(一)实现代理

在配置文件中添加proxy_pass 真实web服务地址;

|--------------|-------------------|
| 代理服务器IP | 192.168.83.30 |
| web服务器IP | 192.168.83.40 |

首先在代理服务器的配置文件中添加 proxy_pass,开启代理服务

在web服务器的根目录下建立好数据文件

此时使用客户端去访问代理服务器就会访问到web服务器的内容

也可以通过监听端口和访问端口进行设置,这样,代理服务器既可以做代理服务器也可以提供web服务

配置代理服务器的配置文件

添加web服务的监听端口

使用客户端访问不同的端口,会得到不同的结果

(二)针对一个URL进行代理

配置代理服务器文件,设置指定的URL

建立web服务器的数据文件

使用客户端进行访问不同的URL

(三)动静分离

动静分离是一种在Web服务器架构设计中常见的策略,它旨在提高系统性能、扩展性和稳定性。动静分离主要是根据请求资源的特性将处理静态内容和动态内容的任务分隔开。

动静分离的概念:

动态内容(Dynamic Content):通常指那些需要服务器实时生成或处理的内容,如通过PHP、Java、Python等语言编写的Web应用程序输出的结果,或者数据库查询返回的数据。这些内容每次请求可能都会产生不同的结果。

静态内容(Static Content):是指那些不会随时间改变且可以被缓存的内容,例如HTML、CSS、JavaScript文件、图片、视频等。这些内容一旦生成,除非有更新,否则可以反复提供给多个用户访问而无需重新生成。

|-------------|--------------------|
| 静态资源服务器 | 192.168.83.40 |
| 动态资源服务器 | 192.168.83.100 |
| 代理服务器 | 192.168.83.30 |

在静态资源服务器主站点目录下建立静态资源文件

在动态资源服务器主站点目录下建立动态资源文件

修改代理服务器的配置文件

cs 复制代码
server {
 listen 80;
 server_name www.pla.com;
 root /data/;
#主站点目录为/data
 location ~* /dynamic {
#此location语句块匹配以/dynameic为起点的URL
 proxy_pass http://192.168.83.100;
#开启代理服务,并指定如果访问本机的/dynamic目录下的所有文件,就是去访问
#http://192.168.83.100/dynamic的相同URL的文件
}
 location ~* \.(jpg|html|txt|mp4)$ {
#匹配所有以.(jpg|html|txt|mp4)结尾的文件,用来区分静态资源
 proxy_pass http://a192.168.83.40;
#开启代理服务,如果匹配到以.(jpg|html|txt|mp4)结尾的文件的。
#就会跳转到 http://192.168.83.40下相同URL的文件
}
}

使用客户机访问静态资源

使用客户机访问动态资源

看起来与重写功能区别不大,但是动静分离可以做负载均衡,并有多个优点

提高响应速度:静态资源可以从缓存或专用服务器快速获取,降低延迟。

负载均衡优化:可以根据静态和动态请求的特点分配不同类型的服务器资源,动态服务器可以专注于计算密集型任务,静态服务器则侧重于I/O性能。

扩展性增强:当流量增加时,可以根据需求独立扩展静态资源服务器和应用服务器的规模。

总结来说,动静分离是通过合理的架构设计,使得系统能更高效地应对不同类型请求的一种优化手段,在现代Web服务中广泛应用。

(四)反向代理缓存

反向代理缓存是Nginx作为高性能Web服务器和负载均衡器时提供的一项重要功能。在Nginx的反向代理场景下,它充当客户端与后端应用服务器之间的中间层,可以缓存来自后端服务器的响应结果,并在后续相同的请求中直接提供已缓存的内容,从而减少对后端服务器的请求次数,提高整体系统的响应速度和可用性。同时,当后端服务器宕机后,在一定时间内依然可以访问。

默认缓存功能关闭,通过添加proxy_cache语句开启缓存功能

首先在代理服务器的主配置文件中添加图片中的信息

如果在子配置文件中配置缓存功能,需要写在定义的include子配置文件的上方,读取配置从上往下,写在下方先读取子配置文件,该行指令可能不会生效

cs 复制代码
proxy_cache_path /data/nginx/proxy_cache
#指定缓存文件存储的路径为 /data/nginx/proxy_cache。

levels=1:1:1
#定义了缓存目录结构层级。这个参数表示将缓存文件按照三级目录进行组织,每一级都是由一个字
#符组成(例如:/0/0/123)。这里的 1:1:1 表示每级目录都只用一个字符来命名,可以根据实际
#需要调整级别和字符长度以适应大量缓存文件的组织需求。

keys_zone=proxycache:20m
#创建了一个名为 proxycache 的共享内存区域,用来存储缓存键值对以及一些元数据,分配给它
#的大小是 20MB。

inactive=120s
#设置缓存项在120秒内未被访问,则被视为过期并可能被清理掉。这意味着如果某个缓存内容在120
#秒内没有被请求,那么它可能会从缓存中移除,释放空间。

max_size=1g
#设置缓存总容量的最大值为1GB。当缓存大小达到1GB时,Nginx会根据其内部策略(如LRU算法)自
#动删除最不活跃或最早添加到缓存中的内容,以便为新内容腾出空间。

在子配置文件中添加信息

cs 复制代码
proxy_cache proxycache;
#在当前作用域内启用缓存,并关联到之前定义的名为 proxycache 的缓存区域。
#这意味着该server或location内的请求响应将根据策略被存储在 
#/data/nginx/proxy_cache 路径下指定的缓存空间中。重启服务后会自动生成该文件

proxy_cache_key $request_uri;
#设置缓存键(key),这里使用了 $request_uri 变量作为缓存键。这意味着缓存
#会基于每个不同的请求URI进行区分,确保每个唯一的URI对应一个独立的缓存项。

proxy_cache_valid 200 302 301 10m;
#指定了对于HTTP状态码为200、302和301的响应,在成功获取后可以缓存10分钟。在此期
#间内,如果有相同的请求到达,Nginx将直接返回缓存中的内容,而不是再次向后端服务器发起请求。

proxy_cache_valid any 5m;
#任何其他未明确指定状态码的响应(包括但不限于404、500等),其缓存有效时间为5分钟。
#这意味着非200/301/302状态码的响应虽然也会被缓存,但其过期时间较短。

此时缓存目录下是没有任何文件的,需要访问之后才会有缓存

当关闭192.168.83.40这个服务器之后,在一定时间内依然可以访问到该信息

增加头部信息

add_header 自定义头部名称 变量(信息)

cs 复制代码
add_header server_ip $server_addr;

#这条指令会在响应头中增加一个名为 "server_ip" 的字段,并将其值设置为当前服务器的IP地址
#($server_addr)。这有助于了解请求经过了哪些代理服务器或负载均衡器。

add_header cache $upstream_cache_status;
#此指令添加了一个 "cache" 字段到响应头中,其值由 $upstream_cache_status 变量提供。
#这个变量表示请求是否被缓存服务命中以及具体的缓存状态,例如 "HIT"(命中)、"MISS"(未
#命中)等。这对于判断反向代理缓存策略是否生效及其效果非常有帮助。

add_header server_name $server_name;
#这个指令添加了一个名为server_name的字段,其值是当前服务器的主机名($server_name)。
#server_name;头部与Nginx内部的ngx_http_proxy_module或ngx_http_fastcgi_module 
#等模块结合使用,用来标识内部请求加速或文件内部重定向等相关信息。

使用客户端访问并查看头部信息

(五)反向代理客户端 IP 透传

在Nginx作为反向代理服务器时通常在接受到客户端的请求后,会去访问真实的web服务器,而此时web服务器的IP地址仅仅只有代理服务器的IP,并不能知道,访问服务器资源的客户端的IP地址

在上面的图片中。作为web服务器,经过反向代理后,只能获得代理服务器的IP(192.168.83.30),

并不能获得客户端IP(192.168.83.50)。

为了能够正确地将客户端的真实IP地址传递给后端应用服务器,需要配置Nginx将客户端IP添加到请求头中。这样,即使经过了Nginx的代理,后端服务器也能识别出原始客户端IP

1.单机代理透传

只有一台代理服务器的情况下进行透传

|--------------|-------------------|
| 代理服务器IP | 192.168.83.30 |
| web服务器IP | 192.168.83.40 |
| 客户端IP | 192.168.83.50 |

首先在代理服务器中添加:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

指令设置了全局的请求头转发规则,将客户端的真实IP地址(或者其他代理服务器传递过来的IP地址)通过 X-Forwarded-For 请求头传递给后端服务器。$proxy_add_x_forwarded_for 变量会自动将客户端IP添加到现有的 X-Forwarded-For 头部中,如果没有则创建一个新的头部。

使用默认的日志格式,并打开将注释删除

使用客户端访问并查看日志web服务(192.168.83.40)的日志

可以看到,开头的192.168.83.30是代理服务器访问web服务器的$remote_addr,最后的192.168.83.50则是客户端的真实IP

2.多机代理透传

代理服务器可能会有多台

|---------------|--------------------|
| 代理服务器1:IP | 192.168.83.30 |
| 代理服务器2:IP | 192.168.83.100 |
| web服务器IP | 192.168.83.40 |
| 客户端IP | 192.168.83.50 |

首先来配置一号代理服务器

添加:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

此时将客户端的IP地址赋予x_forwarded_for

在配置二号代理服务器

此时再去访问第一台代理服务器,就会通过两层代理到真实的web服务器

这是时候查看日志信息

(六)反向代理负载均衡

在上一个节中Nginx可以将客户端的请求转发至单台后端服务器但是无法转发至特定的一组的服务器,而且不能对后端服务器提供相应的服务器状态监测,Nginx 可以基于ngx_http_upstream_module模块提供服务器分组转发、权重分配、状态监测、调度算法等高级功能

反向代理负载均衡是一种将客户端请求分发到一组后端服务器的技术,以分散负载、提高可用性和伸缩性。

由一台代理服务器,指向两台真实的web服务器

|-------------|--------------------|
| 代理服务器 | 192.168.83.30 |
| web服务器1 | 192.168.83.40 |
| web服务器2 | 192.168.83.100 |

在代理服务器上定义地址池,并开启反向代理服务

官方文档:Module ngx_http_upstream_module

upstream只能写在http语句块中

语法为:

upstream 地址池name {

server web服务器IP地址;

server web服务器IP地址;

............

}

建立两个web服务器的数据文件

使用客户端进行访问

可以看到,访问时按地址池中的地址依次访问,而后再次重新依次访问,即访问一次192.168.83.40.再访问192.168.83.100,而后再访问192.168.83.40,这样依次访问,这种方法也是upstream模块默认的负载均衡默认策略。叫做轮询

nginx服务有健康检测机制,如果其中一台服务器宕机,代理服务器并不会将请求发送给宕机的服务器,如果连接超时

1.Nginx负载均衡策略

Nginx负载均衡策略有以下几种

①.轮询

最基本的配置方法,上面的例子就是轮询的方式。每个请求会按时间顺序逐一分配到不同的后端服务器。

②.加权轮询

按分配权重进行轮询,使用weight进行分配

使用客户端进行访问,可以发现,访问比例为3:1

如果设置成5:2,它的访问比例为3:1加2:1

③hash

hash的主要作用是为了保持会话联系。在负载均衡和反向代理的场景下,会话保持(Session Persistence)是一种确保客户端与特定后端服务器之间维持持久连接的技术。当用户在多个请求中需要共享同一会话状态时,例如登录状态、购物车内容等,会话保持尤为重要

hash分为三种

ip_hash

每个请求按访问IP的hash结果分配,同一个IP客户端固定访问一个后端服务器。可以保证来自同一ip的请求被打到固定的机器上

在地址池中添加ip_hash或hash $remote_addr

这样不论访问多少次都会将访问的客户端的IP地址固定在一个服务器上

url_hash

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器。一旦缓存住了资源,再次收到请求,就可以从缓存中读取。

在地址池中添加hash $request_uri

使用客户端进行访问后,根据路径分配后端服务器后,服务器会进行缓存,后续访问会根据访问路径,调取缓存,访问到同一个后端服务器

3.cookie hash

在Nginx中,实现基于Cookie的会话保持(Session Persistence)通常涉及到使用一个自定义的cookie或利用已存在的session cookie来决定将请求转发到哪个后端服务器。这种技术有时被称为"Cookie Hash"或"Cookie Stickiness"

使用客户机访问时加上不同的关键字

另外还有几种策略

least_conn

把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果

fair

此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配

2.状态参数

cs 复制代码
max_conns=number  
#给当前后端server设置最大活动链接数,默认为0表示没有限制
max_fails=number  
#后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测
#多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探
#测后端服务器健康性检查,而非周期性的探测
fail_timeout=time 
#后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行
#检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒
backup  
#设置为备份服务器,当所有后端服务器不可用时,才会启用此备用服务器
down    
#标记为down状态
resolve 
#当server定义的是主机名的时候,当A记录(DNS解析)发生变化会自动应用新IP而不用重启Nginx

这个时候去访问代理服务器,只会将请求发送到192.168.83.40,当所有的服务器都宕机之后,,才会访问到备用的服务器

再去访问时就会访问到备用机器

相关推荐
大G哥3 分钟前
记一次K8S 环境应用nginx stable-alpine 解析内部域名失败排查思路
运维·nginx·云原生·容器·kubernetes
妍妍的宝贝18 分钟前
k8s 中微服务之 MetailLB 搭配 ingress-nginx 实现七层负载
nginx·微服务·kubernetes
醉颜凉20 分钟前
银河麒麟桌面操作系统修改默认Shell为Bash
运维·服务器·开发语言·bash·kylin·国产化·银河麒麟操作系统
苦逼IT运维1 小时前
YUM 源与 APT 源的详解及使用指南
linux·运维·ubuntu·centos·devops
仍有未知等待探索1 小时前
Linux 传输层UDP
linux·运维·udp
zeruns8021 小时前
如何搭建自己的域名邮箱服务器?Poste.io邮箱服务器搭建教程,Linux+Docker搭建邮件服务器的教程
linux·运维·服务器·docker·网站
北城青2 小时前
WebRTC Connection Negotiate解决
运维·服务器·webrtc
疯狂的大狗2 小时前
docker进入正在运行的容器,exit后的比较
运维·docker·容器
XY.散人2 小时前
初识Linux · 文件(1)
linux·运维·服务器
长天一色2 小时前
【Docker从入门到进阶】01.介绍 & 02.基础使用
运维·docker·容器