学完Nginx/OpenResty详解,反向代理与负载均衡配置,能涨薪多少
反向代理与负载均衡配置
接下来介绍Nginx的重要功能:反向代理+负载均衡。单体Nginx的性能虽然不错,但也是有瓶颈的。打个比方:用户请求发起一个请求,网站显示的图片量比较大,如果这个时候有大量用户同时访问,全部的工作量都集中到了一台服务器上,服务器不负重压,可能就崩溃了。高并发场景下,自然需要多台服务器进行集群,既能防止单个节点崩溃导致平台无法使用,又能提高一些效率。一般来说,Nginx完成10万多用户同时访问,程序就相对容易崩溃。
要做到高并发和高可用,肯定需要做Nginx集群的负载均衡,而Nginx负载均衡的基础之一就是反向代理。
演示环境说明
为了较好地演示反向代理的效果,本小节调整一下演示的环境:
不再通过浏览器发出HTTP请求,而是使用curl指令从笔者的CentOS虚拟机192.168.233.128向Windows宿主机器192.168.233.1上的Nginx发起请求。
为了完成演示,在宿主机Nginx的配置文件nginx-proxydemo.conf中配置两个server虚拟主机,一个端口为80,另一个端口为8080。具体如下:
#模拟目标主机server {listen 8080 ;server_name localhost;default_type 'text/html';charset utf-8;location / {echo "-uri= $uri"
"-host= $host""-remote_addr= $remote_addr""-proxy_add_x_forwarded_for= $proxy_add_x_forwarded_for""-http_x_forwarded_for= $http_x_forwarded_for" ;}}#模拟代理主机server {listen 80 default;server_name localhost;default_type 'text/html';charset utf-8;location / {echo "默认根路径匹配: /";}...}
本节用到的配置文件为源码工程nginx-proxy-demo.conf文件。运行本小节的实例前需要修改openresty-start.bat(或openrestystart.sh)脚本中的PROJECT_CONF变量的值,将其改为nginx-proxydemo.conf,然后重启OpenRestry/Nginx。
proxy_pass反向代理指令
这里介绍的proxy_pass反向代理指令处于ngx_http_proxy_module模块,并且注册在HTTP请求11个阶段的content阶段。
proxy_pass反向代理指令的格式如下:
proxy_pass 目标URL前缀;
当proxy_pass后面的目标URL格式为"协议"+"IP[:port]"+"/"根路径的格式时,表示最终的结果路径会把location指令的URI前缀也给加上,这里称为不带前缀代理。如果目标URL为"协议"+"IP[:port]",而没有“/根路径”,那么Nginx不会把location的URI前缀加到结果路径中,这里称为带前缀代理。
1.不带location前缀的代理
proxy_pass后面的目标URL前缀加“/根路径”,实例如下:
#不带location前缀的代理类型location /foo_no_prefix {proxy_pass http://127.0.0.1:8080/;}
通过CentOS的curl指令发出请求
http://192.168.233.1/foo_no_prefix/bar.html,结果如下:
[root@localhost ~]#curl http://192.168.233.1/foo_no_prefix/bar.html
-uri= /bar.html -host= 127.0.0.1 -remote_addr= 127.0.0.1 -proxy_add_x_forwarded_for= 127.0.0.1 -http_x_forwarded_for=
可以看到,$uri变量输出的代理URI为/bar.html,并没有在结果URL中看到location配置指令的前缀/foo_no_prefix。
2.带location前缀的代理
proxy_pass后面的目标URL前缀不加“/根路径”,实例如下:
#带location前缀代理location /foo_prefix {proxy_pass http://127.0.0.1:8080;}
通过CentOS的curl指令发出请求
http://192.168.233.1/foo_prefix/bar.html,结果如下:
[root@localhost ~]#curl http://192.168.233.1/foo_prefix/bar.html
-uri= /foo_prefix/bar.html -host= 127.0.0.1 -remote_addr= 127.0.0.1 -proxy_add_x_forwarded_for= 127.0.0.1 -http_x_forwarded
可以看到,$uri变量输出的代理URI为/foo_prefix/bar.html,也就是说,在结果URL中看到了location配置指令的前缀/foo_prefix。
除了以上两种代理(带location前缀的代理和不带location前缀的代理)之外,还有一种带部分URI路径的代理。
3.带部分URI路径的代理
如果proxy_pass的路径参数中不止有IP和端口,还有部分目标URI的路径,那么最终的代理URL由两部分组成:第一部分为配置项中的目标URI前缀;第二部分为请求URI中去掉location中前缀的剩余部分。
下面是两个实例:
#带部分URI路径的代理,实例1location /foo_uri_1 {proxy_pass http://127.0.0.1:8080/contextA/;}#带部分URI路径的代理,实例2location /foo_uri_2 {proxy_pass http://127.0.0.1:8080/contextA-;}
通过CentOS的curl指令发出两个请求分别匹配到这两个location配置,结果如下:
[root@localhost ~]#curl http://192.168.233.1/foo_uri_1/bar.html
-uri= /contextA/bar.html -host= 127.0.0.1 -remote_addr= 127.0.0.1 -proxy_add_x_forwarded_for= 127.0.0.1 -http_x_forwarded_fo
[root@localhost ~]#curl http://192.168.233.1/foo_uri_2/bar.html
-uri= /contextA-bar.html -host= 127.0.0.1 -remote_addr= 127.0.0.1 -proxy_add_x_forwarded_for= 127.0.0.1 -http_x_forwarded_fo
从输出结果可以看出,无论是例子中的目标URI前缀/contextA/,还是目标URI前缀/contextA-,都加在了最终的代理路径上,只是在代理路径中去掉了location指令的匹配前缀。
新的问题来了:仅仅使用proxy_pass指令进行请求转发,发现很多原始请求信息都丢了。明显的是客户端IP地址,前面的例子中请求都是从192.168.233.128 CentOS机器发出去的,经过代理服务器之后,服务端返回的remote_addr客户端IP地址并不是192.168.233.128,而是变成了代理服务器的IP 127.0.0.1。
如何解决原始信息的丢失问题呢?使用proxy_set_header指令。
proxy_set_header请求头设置指令
在反向代理之前,proxy_set_header指令能重新定义/添加字段传递给代理服务器的请求头。请求头的值可以包含文本、变量和它们的组合。它的格式如下:
#head_field表示请求头,field_value表示值
proxy_pass_header head_field field_value;
前面讲到,由于经过反向代理后,对于目标服务器来说,客户端在本质上已经发生了变化,因此后端的目标Web服务器无法直接拿到客户端的IP。假设后端的服务器是Tomcat,那么在Java中request.getRemoteAddr()取得的是Nginx的地址,而不是客户端的真实IP。
如果需要取得真实IP,那么可以通过proxy_set_header指令在发生反向代理调用之前将保持在内置变量$remote_addr中的真实客户端地址保持到请求头中(一般为X-real-ip),代码如下:
#不带location前缀的代理location /foo_no_prefix/ {proxy_pass http://127.0.0.1:8080/;proxy_set_header X-real-ip $remote_addr;}
在Java端使用request.getHeader("X-real-ip")获取X-real-ip请求头的值就可以获得真正的客户端IP。
在整个请求处理的链条上可能不仅一次反向代理,可能会经过N多次反向代理。为了获取整个代理转发记录,也可以使用proxy_set_header指令来完成,在配置文件中进行如下配置:
#带location前缀的代理location /foo_prefix {proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://127.0.0.1:8080;}
这里使用了$proxy_add_x_forwarded_for内置变量,它的作用就是记录转发历史,其值的第一个地址就是真实地址$remote_addr,然后每经过一个代理服务器就在后面累加一次代理服务器的地址。
上面的演示程序中,如果在Java服务器程序中通过如下代码获取代理转发记录:
request.getHeader("X-Forwarded-For")
那么Java程序获得的返回值为“192.168.233.128,127.0.0.1”,表示最初的请求客户端的IP为192.168.233.128,经过了127.0.0.1代理服务器。每经过一次代理服务器,都会在后边追加上它的IP,并且使用逗号隔开。
为了不丢失信息,反向代理的设置如下:
location /hello {proxy_pass http://127.0.0.1:8080;proxy_set_header Host $host;proxy_set_header X-real-ip $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_redirect off;}
设置了请求头Host、X-real-ip、X-Forwarded-For,分别将当前的目标主机、客户端IP、转发记录保存在请求头中。
proxy_redirect指令的作用是修改从上游被代理服务器传来的应答头中的Location和Refresh字段,尤其是当上游服务器返回的响应码是重定向或刷新请求(如HTTP响应码是301或者302)时,proxy_redirect可以重设HTTP头部的location或refresh字段值。off参数表示禁止所有的proxy_redirect指令。
upstream上游服务器组
假设Nginx只有反向代理没有负载均衡,它的价值会大打折扣。
Nginx在配置反向代理时可以通过负载均衡机制配置一个上游服务器组(多台上游服务器)。当组内的某台服务器宕机时仍能保持系统可用,从而实现高可用。
Nginx的负载均衡配置主要用到upstream(上游服务器组)指令,其格式如下:
语法:upstream name { ... }
上下文:http配置块
upstream指令后面的name参数是上游服务器组的名称;upstream块中将使用server指令定义组内的上游候选服务器。
upstream指令的作用与server有点类似,其功能是加入一个特殊的虚拟主机server节点。特殊之处在于这是上游server服务组,可以包含一个或者多个上游server。
一个upstream负载均衡主机节点的配置实例如下:
#upstream负载均衡虚拟节点
upstream balanceNode {server "192.168.1.2:8080"; #上游候选服务1server "192.168.1.3:8080"; #上游候选服务2server "192.168.1.4:8080"; #上游候选服务3server "192.168.1.5:8080"; #上游候选服务4
}实例中配置的balanceNode相当于一个主机节点,不过这是一个负载均衡类型的特定功能虚拟主机。当请求过来时,balanceNode主机节点的作用是按照默认负载均衡算法(带权重的轮询算法)在4个上游候选服务中选取一个进行请求转发。
实战案例:在随书源码的nginx-proxy-demo.conf配置文件中配置3个server主机和一个upstream负载均衡主机组。此处配置了一个location块,将目标端口为80的请求反向代理到upstream主机组,以方便负载均衡主机的行为。
实战案例的配置代码节选如下:
#负载均衡主机组,给虚拟主机1与虚拟主机2做负载均衡upstream balance {server "127.0.0.1:8080"; #虚拟主机1server "127.0.0.1:8081"; #虚拟主机2}#虚拟主机1server {listen 8080;server_name localhost;location / {echo "server port:8080" ;}}#虚拟主机2server {listen 8081 ;server_name localhost;location / {echo "server port:8081" ;}}#虚拟主机3:默认虚拟主机server {listen 80 default;...#负载均衡测试连接location /balance {proxy_pass http://balance; #反向代理到负载均衡节点}}
运行本小节的实例前需要修改启动脚本openresty-start.bat(或openresty-start.sh)中的PROJECT_CONF变量的值,将其改为nginx-proxy-demo.conf,然后重启OpenRestry/Nginx。
在CentOS服务器中使用curl命令请求
http://192.168.233.1/balance链接地址(IP根据Nginx情况而定),并且多次发起请求,就会发现虚拟主机1和虚拟主机2被轮流访问到,具体的输出如下:
[root@localhost ~]#curl http://192.168.233.1/balance
server port:8080
[root@localhost ~]#curl http://192.168.233.1/balance
server port:8081
[root@localhost ~]#curl http://192.168.233.1/balance
server port:8080
[root@localhost ~]#curl http://192.168.233.1/balance
server port:8081
[root@localhost ~]#curl http://192.168.233.1/balance
server port:8080
通过结果可以看出,upstream负载均衡指令起到了负载均衡的效果。默认情况下,upstream会依照带权重的轮询方式进行负载分配,每个请求按请求顺序逐一分配到不同的上游候选服务器。
upstream的上游服务器配置
upstream块中将使用server指令定义组内的上游候选服务器。内部server指令的语法如下:
语法:server address [parameters];
上下文:upstream配置块
此内嵌的server指令用于定义上游服务器的地址和其他可选参数,它的地址可以指定为域名或IP地址带有可选端口,如果未指定端口,就使用端口80。
内嵌的server指令的可选参数大致如下:
(1)weight=number(设置上游服务器的权重):默认情况下,upstream使用加权轮询(Weighted Round Robin)负载均衡方法在上游服务器之间分发请求。weight值默认为1,并且各上游服务器的weight值相同,表示每个请求按先后顺序逐一分配到不同的上游服务器,如果某个上游服务器宕机,就自动剔除。
如果希望改变某个上游节点的权重,就可以使用weight显式进行配置,参考实例如下:
#负载均衡主机组upstream balance {server "127.0.0.1:8080" weight=2; #上游虚拟主机1,权重为2server "127.0.0.1:8081" weight=1; #上游虚拟主机2,权重为1}
权重越大的节点,将被分发到更多请求。
(2)max_conns=number(设置上游服务器的最大连接数):
max_conns参数限制到上游节点的最大同时活动连接数。默认值为零,表示没有限制。如果upstream服务器组没有通过zone指令设置共享内存,那么在单个Worker工作进程范围内对上游服务的最大连接数进行限制;如果upstream服务器组通过zone指令设置了共享内存,那么在全体的Worker工作进程范围内对上游服务进行统一的最大连接数限制。
(3)backup(可选参数):backup参数标识该server是备份的上游节点,当普通的上游服务(非backup)不可用时,请求将被转发到备份的上游节点;当普通的上游服务(非backup)可用时,备份的上游节点不接受处理请求。
(4)down(可选参数):down参数标识该上游server节点为不可用或者永久下线的状态。
(5)max_fails=number(最大错误次数):如果上游服务不可访问了,如何判断呢?max_fails参数是其中之一,该参数表示请求转发最多失败number次就判定该server为不可用。max_fails参数的默认次数为1,表示转发失败1次,该server即不可用。如果此参数设置为0,就会禁用不可用的判断,一直不断地尝试连接后端server。
(6)fail_timeout=time(失败测试的时间长度):这是一个失效监测参数,一般与上面的参数max_fails协同使用。fail_timeout的意思是失败测试的时间长度,指的是在fail_timeout时间范围内最多尝试max_fails次,就判定该server为不可用。fail_timeout参数的默认值为10秒。
server指令在进行max_conns连接数配置时,Nginx内部会涉及共享内存区域的使用,配置共享内存区域的指令为zone,其具体语法如下:语法:zone name [size];
上下文:upstream配置块
zone的name参数设置共享内存区的名称,size可选参数用于设置共享内存区域的大小。如果配置了upstream的共享内存区域,那么其运行时状态(包括最大连接数)在所有的Worker工作进程之间是共享的。在name相同的情况下,不同的upstream组将共享同一个区,这种情况下,size参数的大小值只需设置一次。
下面是一个server指令和zone指令的综合使用实例:
upstream zuul {
zone upstream_zuul 64k; //名称为upstream_zuul,大小为64KB的共享内存区域
server "192.168.233.128:7799" weight=5 max_conns=500;
server "192.168.233.129:7799" fail_timeout=20s max_fails=2; //默认权重为1
server "192.168.233.130:7799" backup; //后备服务
}
upstream的负载分配方式
upstream大致有3种负载分配方式,下面一一介绍。
1.加权轮询
默认情况下,upstream使用加权轮询(Weighted Round Robin)负载均衡方法在上游服务器之间分发请求,默认的权重weight值为1,并且各上游服务器weight值相同,表示每个请求按到达的先后顺序逐一分配到不同的上游服务器,如果某个上游服务器宕机,就自动剔除。
指定权重weight值,weight和分配比率成正比,用于后端服务器性能不均的情况。下面是一个简单的例子:
upstream backend {server 192.168.1.101 weight=1;server 192.168.1.102 weight=2;server 192.168.1.103 weight=3;}
2.hash指令
基于hash函数值进行负载均衡,hash函数的key可以包含文本、变量或二者的组合。hash函数负载均衡是一个独立的指令,指令的格式如下:
语法:hash key [consistent];
上下文:upstream配置块注意,如果upstream组中摘除掉一个server,就会导致hash值重
新计算,即原来的大多数key可能会寻址到不同的server上。若配置有consistent参数,则hash一致性将选择Ketama算法。这个算法的优势是,如果有server从upstream组里摘除掉,那么只有少数的key会重新映射到其他的server上,即大多数key不受server摘除的影响,还走到原来的server。这对提高缓存server命中率有很大帮助。下面是一个简单的通过请求的$request_uri的hash值进行负载均衡的例子:
upstream backend {hash $request_uri consistent;server 192.168.1.101 ;server 192.168.1.102 ;server 192.168.1.103 ;
}
3.ip_hash指令
基于客户端IP的hash值进行负载平衡,这样每个客户端固定访问同一个后端服务器,可以解决类似session不能跨服务器的问题。如果上游server不可用,就需要手工摘除或者配置down参数。ip_hash是一条独立的指令,其使用的示例如下:
upstream backend {ip_hash;server 192.168.1.101:7777;server 192.168.1.102:8888;server 192.168.1.103:9999;}
本文给大家讲解的内容是Nginx/OpenResty详解,反向代理与负载均衡配置
- 下篇文章给大家讲解的是 Nginx/OpenResty详解,Nginx Lua编程;
- 觉得文章不错的朋友可以转发此文关注小编;
- 感谢大家的支持!
学完Nginx/OpenResty详解,反向代理与负载均衡配置,能涨薪多少相关推荐
- Nginx代理支持GRPC的反向代理和负载均衡配置
Nginx代理gRPC反向代理和负载均衡配置 linux版本安装 一.准备和安装 #指定目录安装( /home/yyt/nginxgrpc) mkdir /home/yyt/nginxgrpc cd ...
- nginx和tomcat实现反向代理、负载均衡和session共享
这类的文章非常多,nginx和tomcat实现反向代理.负载均衡实现非常easy,能够參照http://blog.csdn.net/liuzhigang1237/article/details/888 ...
- Nginx的反向代理与负载均衡--配置Nginx
前言 Nginx 是一个非常轻量级的服务器,他虽轻但是他最大的优点就是可以承载大量的并发,所以说一般的话很少有用 Node 直接去做服务器让用户去访问的,因为 Node 本身就需要做非 常非常多的事情 ...
- Nginx反向代理实现负载均衡配置图解
come from: http://www.php100.com/html/program/nginx/2013/0905/5529.html 负载均衡配置是超大型机器需要考虑的一些问题,同时也 ...
- Nginx简单入门与反向代理和负载均衡
什么是Nginx Nginx 是一款高性能的 http 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器.由俄罗斯的程序设计师伊戈尔•西索夫(Igor Sysoev)所开发,官方测 ...
- Nginx Oracle反向代理与负载均衡配置
场景需求: 由于Oracle RAC模式在生产环境不建议使用SCAN IP,使用Nginx完成TCP/UTP三层的负载. 实施环境: Nginx版本:1.14.2 Nginx服务器IP: ...
- nginx的重定向,反向代理以及负载均衡
试验环境: 本次试验中的服务器全用的是CentOS-6.4-x86_64操作系统: nginx服务器地址:192.168.80.10 客户端主机地址:192.168.80.1 软件包下载地址: hea ...
- Nginx入门简介和反向代理、负载均衡、动静分离理解
场景 Nginx简介 Nginx ("engine x")是一个高性能的 HTTP 和反向代理服务器 特点是占有内存少,并发能力强,事实上 nginx 的并发能力确实在同类型的网页 ...
- 【Nginx 之一】Nginx初体验(反向代理、负载均衡、动静分离)
1. 概述 1.1 什么是Nginx Nginx 是高性能的 HTTP 和反向代理的web服务器,处理高并发能力是十分强大的,能经受高负 载的考验,有报告表明能支持高达 50,000 个并发连接数 ...
最新文章
- 团队作业1(陈爽、夏江华、李瑞超、甘彩娈、吕乐乐)
- java array 元素的位置_Java常见面试题 非常实用「个人经验」
- Android NDK学习笔记4:JNI访问Java构造函数
- mapreduce,map后面跟map是什么操作???
- mysql 剔除不可见字符_机器视觉OCR字符检测在食品瓶盖上的应用
- ⑥又是星期五,小试牛刀(编写定制标签)
- 每日英语:Lighting: Twigs Shine in Home Decor
- 第五篇:路由网关(zuul) zuul路由 服务过滤 (Finchley版本)V2.0_dev
- extras mibs php7,ubuntu编译安装php7遇到的问题及解决方案
- 关于System.AccessViolationException异常
- python部署到linux打开ie_Linux上部署python+selenium+webdriver常见问题解决方案
- 双向BUCK BOOST DCDC变换器仿真模型 BUCK BOOST 拓扑结构,电压电流双闭环控制策略
- html基础教程全集零基础入门到精通汇总整理(附详细的学习路线图)
- activex控件 java_ActiveX控件不自动安装
- 常用颜色名称与RGB数值对照表
- 汽车操作系统攻防综述
- 显卡测试软件3d mark,AllBenchmark(3D显卡测试工具)1.3 免费版
- python3安装scapy_scapy安装
- pthread_setspecific函数与pthread_getspecific函数
- 第6课 Altium Designer20(AD20)+VESC6.4实战教程:绘制原理图3(北冥有鱼)
热门文章
- mysql智能停车场,jsp357智能停车场管理系统 双数据库版 mysql
- 电脑版QQ个人资料无法设置问题
- Computer:Windows系统装机之一键U盘启动盘装系统制作图文教程之详细攻略
- 中国海洋大学第四届朗讯杯高级组 Cash Cow
- 计算机多媒体信息技术,从多媒体技术走向信息技术
- Java面向对象三大特征:封装、继承、多态
- 河南理工大学计算机应用,河南理工大学第四届计算机应用技能公开赛.doc
- 滑坡泥石流的防御措施_如何预防泥石流?预防泥石流的措施有哪些?
- f分布表完整图a=0.01_使用 Infer.NET 评价竞争对手
- Cubis Systems提供入孔井和电缆管道系统的3D BIM CAD工程数据