linux-nginx-3(反向代理+负载均衡)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux-nginx-3(反向代理+负载均衡)相关的知识,希望对你有一定的参考价值。
nginx的反向代理
反向代理(Reverse Proxy)方式是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器;并将从服务器上得到的结果返回给Internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
通常的代理服务器,只用于代理内部网络对Internet的连接请求,客户机必须指定代理服务器,并将本来要直接发送到Web服务器上的http请求发送到代理服务器中。当一个代理服务器能够代理外部网络上的主机,访问内部网络时,这种代理服务的方式称为反向代理服务。
nginx可以作为七层协议上的负载均衡主机,即在应用层上的负载均衡主机,七层负载是面向服务的,报文已经被转发至用户空间,这是不同于四层负载的地方(四层负载在内核(TCP协议栈)就被转发给后台RS)。
Nginx通过proxy模块实现反向代理功能。在作为web反向代理服务器时,nginx负责接收客户请求,并能够根据URI、客户端参数或其它的处理逻辑将用户请求调度至上游服务器上(upstream server)。nginx在实现反向代理功能时的最重要指令为proxy_pass,它能够将location定义的某URI代理至指定的上游服务器(组)上。
⑴proxy_pass URL;
设置后端服务器的协议和地址;这条指令可以设置的协议是“http”或者“https”,而地址既可以使用域名或者IP地址加端口(可选)的形式来定义:
proxy_pass http://localhost:8000/uri/;
如果解析一个域名得到多个地址,所有的地址都会以轮转的方式被使用。当然,也可以使用服务器组来定义多个地址。
如果proxy_pass没有使用URI,传送到后端服务器的请求URI一般是客户端发起的原始URI,如果nginx改变了请求URI,则请求路径与配置中的路径的匹配部分将被替换为指令中定义的URI:
若nginx接到的请求的uri是/name/a.html
location /name/ {
proxy_pass http://192.168.30.20/remote/;
} #传送到后端服务器的URI是/remote/a.html
location /name/ {
proxy_pass http://192.168.30.20;
} #传送到后端服务器的URI是/name/a.html
location /name/ {
proxy_pass http://192.168.30.20/;
} #注意与上面用法的区别,这里地址末尾带有斜线,实际上被认为定义了URI,该“/”会替换“/name/",传送到后端服务器的URI是/a.html。
如果使用正则表达式定义路径,则proxy_pass指令不应使用URI
location ~ .php$ {
proxy_pass http://127.0.0.1;
}
在需要代理的路径中,使用rewrite指令改变了URI,那么nginx将使用重写后的URI处理请求,而忽略proxy_pass指令设置的URI。如下面所示的例子中,传送给上游服务器的URI为/index.php?page=<match>。
location / {
rewrite /(.*)$ /index.php?page=$1 break;
proxy_pass http://localhost:8080;
}
⑵proxy模块的其它指令
①proxy_connect_timeout time;
与后端服务器建立连接的超时时间。一般不可能大于75秒;
②proxy_cookie_domain off; #取消当前配置级别的所有proxy_cookie_domain指令
proxy_cookie_domain domain replacement;
设置“Set-Cookie”响应头中的domain属性的替换文本,其值可以为一个字符串、正则表达式的模式或一个引用的变量;例如:
proxy_cookie_domain localhost example.org;
说明:
浏览器对 Cookie 有很多限制,如果 Cookie 的 Domain 部分与当前页面的 Domain 不匹配就无法写入。所以如果请求 A 域名,服务器 proxy_pass 到 B 域名,然后 B 服务器输出 Domian=B 的 Cookie,前端的页面依然停留在 A 域名上,于是浏览器就无法将 Cookie 写入。
不仅是域名,浏览器对 Path 也有限制。我们经常会 proxy_pass 到目标服务0器的某个 Path 下,不把这个 Path 暴露给浏览器。这时候如果目标服务器的 Cookie 写死了 Path 也会出现 Cookie 无法写入的问题。
③proxy_cookie_path off;
proxy_cookie_path path replacement;
设置“Set-Cookie”响应头中的path属性的替换文本,其值可以为一个字符串、正则表达式的模式或一个引用的变量;例如:
proxy_cookie_path /two/ /;
若“Set-Cookie”响应头含有属性“path=/two/some/uri/”,那么该指令会将这个属性改写为“path=/some/uri/”。
④proxy_hide_header field;
nginx默认不会将“Date”、“Server”、“X-Pad”,和“X-Accel-...”响应头发送给客户端。该指令则可以设置额外隐藏的响应头,这些响应头也不会发送给客户端。相反的,如果希望允许传递某些响应头给客户端,可以使用proxy_pass_header指令。
⑤proxy_set_header field value;
重新定义或者添加发往后端服务器的请求头。value可以包含文本、变量或者它们的组合。例如:
proxy_set_header X-Real-IP $remote_addr; #给请求头中添加客户端IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
默认情况下,只有两个请求头会被重新定义:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
如果某个请求头的值为空,那么这个请求头将不会传送给后端服务器:
proxy_set_header Accept-Encoding "";
⑥proxy_pass_request_headers on|off; #是否将http首部发往上游服务器
⑦proxy_pass_request_body on|off; #是否将http请求报文的包体部分发往上游服务器
⑧proxy_redirect [default|off|redirect replacement];
修改上游服务器传来的响应头中的"Location"和"Refresh"字段。例如:
proxy_redirect http://localhost:8000/two/ http://frontend/one/;
replacement字符串可以省略服务器名:
proxy_redirect http://localhost:8000/two/ /;
此时将使用代理服务器的主域名和端口号来替换。如果端口是80,可以不加。
⑨proxy_send_timeout time;
在连接断开之前两次发送至upstream server的写操作的最大间隔时长;
⑩proxy_read_timeout time;
在连接断开之前两次从接收upstream server接收读操作的最大间隔时长;
⑶proxy模块的内置变量
①$proxy_host:后端服务器的主机名和端口;
②$proxy_port:后端服务器的端口;
③$proxy_add_x_forwarded_for
将$remote_addr变量值添加在客户端“X-Forwarded-For”请求头的后面,并以逗号分隔。 如果客户端请求未携带“X-Forwarded-For”请求头,$proxy_add_x_forwarded_for变量值将与$remote_addr变量相同
设置示例:
proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 30; proxy_send_timeout 15; proxy_read_timeout 15;
当在192.168.2.18的配置文件中定义了反向代理,指向192.168.2.29,此时我们访问192.168.2.18 就会把请求代理转发给192.168.2.29这台主机
二、缓存服务器功能
nginx做为反向代理时,能够将来自上游服务器的响应缓存至本地,并在后续的客户端请求同样内容时直接从本地构造响应报文。nginx使用磁盘做缓存
nginx缓存大致上由两部分组成:
cache:共享内存(存储键和缓存对象元数据),查找在内存上
data:数据在磁盘空间
(1) proxy_cache_path:定义缓存空间(不能定义在server段中,定义在http段中),属于proxy模块
proxy_cache_path [levels=levels] keys_zone=name:size [inactive=time] [max_size=size] [loader_files=number] [loader_sleep=time] [loader_threshold=time] ;定一个用记保存缓存响应报文的目录,及一个保存缓存对象的键及响应元数据的共享内存区域(keys_zone=name:size),其可选参数有:
levels:每级子目录名称的长度,有效值为1或2,每级之间使用冒号分隔,最多为3级;1:2表示两个级别目录,一级子目录由一个字符组成,二级子目录由二个字符组成 keys_zone:给共享内存命名,存储键的区域,可以定义多个区域,每个区域要有个名称引用。 inactive:非活动缓存项从缓存中剔除之前的最大缓存时长; max_size:缓存空间大小的上限,当需要缓存的对象超出此空间限定时,缓存管理器将基于LRU算法对其进行清理; loader_files:缓存加载器(cache_loader)的每次工作过程最多为多少个文件加载元数据; loader_sleep:缓存加载器的每次迭代工作之后的睡眠时长; loader_threashold:缓存加载器的最大睡眠时长;
如 proxy_cache_path /nginx/cache levels=1:1 keys_zone=nginx_cache:64m
(2) proxy_cache zone | off; #定义一个用于缓存的共享内存区域,其可被多个地方调用;zone为我们之前定义的keys_zone名字,如之前的nginx_cache
(3)proxy_cache_min_uses:某响应报文被缓存之前至少应该被请求的次数;
(4) proxy_cache_lock on | off; #启用此项,可在缓存未命令中阻止多个相同的请求同时发往upstream,其生效范围为worker级别
(5)proxy_cache_lock_timeout time; #proxy_cache_lock功能的锁定时长;
(6)proxy_cache_min_uses number; #某响应报文被缓存之前至少应该被请求的次数;
(7)proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 |http_504 | http_403 | http_404 | off ...; 在无法联系到upstream服务器时的哪种情形下(如error、timeout或http_500等)让nginx使用本地缓存的过期的缓存对象直接响应客户端请求
例如 proxy_cache_usr_stale error ;
(8)proxy_cache_valid [code ...] time;
用于为不同的响应设定不同时长的有效缓存时长,例如: proxy_cache_valid 200 302 10m;为200和302响应设置缓存时长为10分钟
(9) proxy_cache_methods GET | HEAD | POST ...; #为哪些请求方法启用缓存功能;默认GET和HEAD
如proxy_cache_methods GET;把GET请求给缓存
(10) proxy_cache_bypass string;
设定在哪种情形下,nginx将不从缓存中取数据。例如:
proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;
proxy_cache_bypass $http_pragma $http_authorization;
(11) proxy_cache_key string; #设定在存储及检索缓存时用于“键”的字符串,可以使用变量为$uri其值,但使用不当时有可能会为同一个内容缓存多次;另外,将用户私有信息用于键可以避免将用户的私有信息返回给其它用户;
例如:proxy_cache_key "$host$request_uri;
负载均衡
负载均衡使用的是upstream模块,upstream模块可定义一个新的上下文,它包含了一组upstream服务器,这些服务器可能被赋予了不同的权重、不同的类型、可以检查各个负载服务器的状态甚至可以基于维护等原因被标记为down。
配置语法:
upstream 服务器列表名称 {
server address [parameters];
...
}
upstream模块常用的指令有:
weight:权重;默认为1 max_fails=number;设定Nginx与服务器通信的尝试失败的次数。在fail_timeout参数定义的时间段内,如果失败的次数达到此值,Nginx就认为服务器不可用。在下一个fail_timeout时间段,服务器不会再被尝试。失败的尝试次数默认是1。设为0就会停止统计尝试次数,认为服务器是一直可用的。 fail_timeout=time #默认是10秒 backup #标记为备用服务器。当主服务器不可用以后,请求会被传给这些服务器。 down #标记服务器永久不可用,可以跟ip_hash指令一起使用
upstream模块的其它负载均衡算法(用于upstream上下文):
①ip_hash;
作用同lvs中的sh调度算法,将来自于同一个客户端的请求始终调度至同一台后端服务器(除了当服务器不可用的时候)
②least_conn;
将请求发送到活动连接数最少的那台服务器。如果这样的服务器有多台,就尝试按加权轮循来调度
③sticky cookie name [expires=time] [domain=domain] [httponly] [secure] [path=path];
session绑定,将来自于同一个客户端的请求始终调度至同一台后端服务器,从而实现客户端与后端服务器的session保持。
ip_hash指令无法实现对内网NAT用户的均衡,而sticky指令可以做到;
◆sticky工作原理:
1.浏览器首次发起请求,请求头未带cookie。nginx接收请求,发现请求头没有cookie,则以轮询方式将请求代理给后端服务器。
2.后端服务器处理完请求,将响应头和内容返回给nginx。
3.nginx生成cookie,返回给客户端浏览器。cookie的值与后端服务器对应,可能是明文,也可能是md5、sha1等Hash值。
4.浏览器接收请求,并创建cookie。
5.浏览器再次发送请求时,带上cookie。
6.nginx接收到cookie,直接转给对应的后端服务器
参数说明:
domain:cookie作用的域名
path:cookie作用的路径
expires:cookie的过期时长
7、health_check [interval=time] [fails=number] [passes=number] [uri=uri] [match=name];
对上游服务器组进行健康状态检测,用于location中;
参数说明:
interval=time #检测的间隔时长,默认为5秒
fails=number #连续检测失败多少次即认为上游服务器不可用,默认为1次
passes=number #上游服务器从不可用到可用状态时需要连续检测的次数,默认为1次
uri=uri #定义用于健康检测的URI,默认为“/”,即默认检测目标服务器的主页
match=name #指定一段配置来当作检测条件,默认当响应码为2XX或3XX时认为上游服务器是可用的
uptream使用注意:
①只能用于http上下文
②各server只能直接使用IP或主机名,不要加协议
⑶默认情况下,nginx按加权轮转的方式将请求代理到各上游服务器。与上游服务器通信的时候,如果出现错误,请求会被传给下一个服务器,直到所有可用的服务器都被尝试过。如果所有服务器都返回失败,客户端将会得到最后通信的那个服务器的(失败)响应结果。
⑷地址可以是域名或者IP地址,端口是可选的(默认是80),或者是指定“unix:”前缀的UNIX域套接字的路径。如果一个域名解析到多个IP,本质上是定义了多个server。
例如:
http{
listen 80;
upstream php_nginx{
server 192.168.2.29 weight=2;
server 192.168.2.30:8080 weight=3 max_fails=5 fail_timeout=30;
server 192.168.2.109 backup;
}
location / {
proxy_pass http://php_ngix;
health_check interval=30 fails_time=5 url=/ match=check-php;
}
mtach check-php{
status 200;
header Content-Type = text/html;
body ~ "Welcome to nginx!";
}
}
以上是关于linux-nginx-3(反向代理+负载均衡)的主要内容,如果未能解决你的问题,请参考以下文章