1、常见负载均衡的方式(概念普及)

【1】用户手动选择

例如我们玩游戏,服务器会显示当前服务器的状态是拥挤、繁忙、还是空闲,然后用户根据自己实际需要,选择自己想去的服务器。

如果服务器人太多(达到上限),则触发排队,比如猪场主推的一些游戏,在刚上线的时候通常都特别火,要排很久,还有戏称阴兵的存在。

这个适合用户和用户之间需要交互的情况(且跨服务器之间无法交互,或交互比较麻烦)。

【2】DNS解析控制

需要知道一个前提,你访问同一个域名,第一次可能是1xx.1xx.1xx.1,第二次可能是1xx.1xx.1xx.2(即不同的ip)。

但由于这两个都是网站的服务器,所以不管访问哪个都一样。

在我们访问域名的时候,DNS解析服务器,会将你的域名转为IP,因此我们具体访问哪一个IP上的服务器,是根据DNS解析服务器来决定的。

以阿里云为例,我们可以配置云解析。

具体来说,我们可以设置 a.test.com 被解析为 1xx.1xx.1xx.1 和 1xx.1xx.1xx.2 ,甚至更多。

效果是当访问 a.test.com 时,用户可能跳转到 1xx.1xx.1xx.1 和 1xx.1xx.1xx.2 或者其他你设置的 ip 上。

缺点:

  1. 假如 1xx.1xx.1xx.1 服务器挂了,所以被导向这个 IP 地址的流量,都不会得到相应;
  2. 不是真负载均衡,特别在各个服务器高压力的情况下,部分服务器可能先达到 100% 负载,然后出现问题。

【3】涉及到网络七层协议的负载均衡

分为第四层(传输层)和第七层(网络层)两种。

第四层的负载均衡简单来说,当你访问到一个 IP 地址(外部)时,他会被映射到内部多个预先保存的 IP 地址(内部)中的一个。

第七层的负载均衡,是根据HTTP请求头的内容,来指向不同的服务器。

硬件实现,通常是通过交换机。软件实现,就各有所长了。

例如 Nginx 就是典型的通过软件的第七层来实现负载均衡。

【4】混合形式

比如:

  • 根据访问者的地区,找不同地区的机房(例如来自长三角的流量找上海的机房)
  • 根据访问者的网络,找不同运营商的机房(电信的找电信机房)
  • 进了机房后,根据机子的负载不同,找负载低的服务器

2、Nginx反向代理的基本配置

配置很简单,核心属性是 proxy_pass,可以直接指向域名

解释:

当访问 c.test.com 时,触发这里的反向代理配置(当然,需要先配置好host,让这个域名指向nginx服务器的IP),然后会重定向到 proxy_pass 配置的IP地址。

即:【访问nginx服务器】–反向代理–>【103.94.185.215:3000】

server {listen 80;# 监听的域名是 c.test.com,即用户访问 c.test.com 时,触发这个配置server_name c.test.com;location / {# 访问根域名,跳转到 http://103.94.185.215:3000/ 这个IP,这个IP是我自己的网站proxy_pass http://103.94.185.215:3000/;}
}

3、反向代理到多个服务器

以上只能反向代理到单个服务器,nginx也支持配置反向代理到多个服务器。

通过借用 upstream 属性,存储一个服务器列表,具体写法如下:

# 配置服务器列表
upstream my_server_list{server 185.186.147.210;server 103.94.185.215:3000;
}# 配置 server
server {listen 80;# 监听的域名是 c.test.com,即用户访问 c.test.com 时,触发这个配置server_name c.test.com;location / {# 反向代理到 my_server_list 池中proxy_pass http://my_server_list;}
}

注意:

  • upstream 和 server 的配置是同一级的;
  • 每一个 server 一行,只写ip即使用默认端口80,也可以写上端口;
  • 这里是最基本的配置,将在下面不断增加更复杂的内容;

4、属性详解

4.1 proxy_set_header

位置:

http, server, location

格式:

proxy_set_header field value;# 默认值
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;

说明:

  1. 这个属性用于配置nginx服务器传给后端服务器的请求的 request 的 header 属性;
  2. 具体来说,使用反向代理时,流量的流向形式是:【客户端】->【nginx服务器】->【后端服务器】;
  3. 以host属性为例,默认情况下:
    1. 当访问 c.test.com 时,【客户端】->【nginx服务器】这一步,request 的 header 为 c.test.com;
    2. 而【nginx服务器】->【后端服务器】这一步的header为 proxy_pass 属性中,http://属性后的字符串的值。例如 proxy_pass http://127.0.0.1:3000; ,则 host 的值为 127.0.0.1:3000
    3. 如果是 proxy_pass http://my_server_list;,那么传给后端服务器的header里 host 字段值为 my_server_list
  4. 如果想让 Host 值等于用户访问的域名,则需要这么设置 proxy_set_header Host $host;
  5. 也可以使用 $http_host 来替代 $host,这个不同之处在于,当访问的不是 80/443 端口时,$http_host 会带上端口值(示例:c.test.com:81
    1. 几个属性值的区别,可以参考这个链接 关于nginx中host, server_name, http_host的区别
  6. 你也可以通过这个字段,来添加你想自定义的 header 属性对,或者覆写已有的字段值;
  7. 注意: field 里的大写字母,在后端拿到的header里,大写字母都已经被转为小写字母了。
  8. 我们之前在【07、日志】里面,通过 http_x_forwarded_for 来拿取重定向之前,用户真实的 IP 地址,因此我们通常在做反向代理的时候,应该通过这个属性,将用户真实 IP 地址添加进去。写法如下:proxy_set_header X-Forwarded-For $remote_addr;

如果自定义header的话,示例配置如下:

server {listen 80;# 监听的域名是 c.test.com,即用户访问 c.test.com 时,触发这个配置server_name c.test.com;location / {# 反向代理到 my_server_list 池中proxy_pass http://my_server_list;# 在发送到后端服务器的 request 里的 header 里添加属性头 Abc ,值为 abcdproxy_set_header Abc abcd;}
}

后端服务器打个日志:

console.log('header-abc-', req.headers['abc']);

输出结果:

header-abc- abcd

4.2 upstream

upstream 在配置负载均衡时,提供了一个服务器池。每个服务器以server 关键字作为开头,配置一行。

upstream的配置和server配置平级。

server的配置很简单,都用下面这个:

server {listen 80;server_name c.test.com;location / {proxy_pass http://my_server_list/;}
}

【默认配置】

  • 轮询:在默认情况下,upstream按照轮询的方式实现负载,条件是时间;
upstream my_server_list{server 185.186.147.210;server 103.94.185.215:3000;
}

【server】

语法:

server name [参数]
  • server:关键字,不变;
  • name:域名、IP地址、端口号(不能只有端口号)、UNIX Socket;

【权重:weight】

写在 server 行中,默认值为1,值越大,负载权重越大。

当在 server 的服务器地址(例如IP)后面添加 weight 属性时,说明按权重的方式实现负载均衡。

weight 是通过数值的不同实现概率不同的,以下为例,理论上上面服务器被轮训到的概率是下面服务器的1/4;

upstream my_server_list{server 185.186.147.210 weight=1;server 103.94.185.215:3000 weight=4;
}

【ip_hash】

每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。

简单来说,你第一次访问被分配到A服务器,那么后面永远都是A服务器来对你进行处理了。适合需要保存用户登录状态(session)的场景(但又做不到session共享的情况)。

这种情况缺点是不能保证每个服务器负载是相同的。

写法:

upstream my_server_list{ip_hash;server 185.186.147.210;server 103.94.185.215:3000;
}

【fair:第三方插件】

需要安装第三方插件,效果是:按后端服务器的响应时间来分配请求,响应时间短的优先分配。

写法类似 ip_hash,安装方法谷歌搜索:【nginx安装fair】,下同。

【url_hash:第三方插件】

需要安装第三方插件,效果是:按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。

写法类似 ip_hash

【down】

写在 server 行中,表示该服务器暂时不参加负载。

如以下示例中,你永远只能访问到第一个服务器。

upstream my_server_list{server 185.186.147.210 down;server 103.94.185.215:3000;
}

之所以写 down,而不是直接注释掉。是因为 nginx 在做负载均衡时,是根据已有服务器做处理的。

例如4个server时的 ip_hash 和3个服务器的 ip_hash,在ip不变的情况下,命中的服务器是不一样的。

4个服务器一个后面写down,那还是四个服务器,而不是三个服务器。而注释掉,就真的只有3个服务器了。

【max_fails】

写在 server 行中,表示允许该服务器请求失败的次数,默认值为1,超过最大次数时,将被 proxy_next_upstream 这一行的配置所处理。

注意,这个过程不会被用户所感知,会被nginx所自动排除。

【fail_timeout】

写在 server 行中,表示在 max_fails 次失败后,该 server 暂停的时间(即在之后一段时间里,不会被nginx放在负载均衡池中),默认值是 10s (即10秒)。

如果将这个值设置为 fail_timeout=0,则表示如果遇见偶尔的错误情况,并不会将这个 server 排除在之后的请求(或者暂停一段时间不去请求这个服务器)。

示例写法如下(第一个服务器允许3次失败,失败后移出5秒)

upstream my_server_list{server 185.186.147.210 max_fails=3 fail_timeout=5s;server 103.94.185.215:3000;
}

【backup】

写在 server 行中,表示在其他服务器都挂了(无一存活)的情况下,请求这个服务器。

默认情况下不会被请求,只有一台挂了的话,也不会被请求。

如下示例:

upstream my_server_list{server 185.186.147.210 max_fails=3 fail_timeout=5s;server 127.0.0.1:3000;server 103.94.185.215:3000 backup;
}

若是前2个只有一个挂的情况下,也不会访问第三个服务器的。只有前2个都挂的情况下,才会访问。

适合在服务器都挂的情况下,给出一个静态的错误提示页面(静态页面是很难挂的)。

4.3、upstream 的相关变量

  • $upstream_addr:处理请求的 upstream 服务器地址;
  • $upstream_status:upstream 服务器的应答状态;
  • $upstream_response_time:upstream服务器的响应时间(秒),多个响应时间以逗号和冒号分割;
  • $upstream_http_$HEADER:任意的HTTP协议头信息。注意,这个并不是指客户端请求的HTTP协议头里的信息。貌似是需要额外配置的。
  • 这些东西可以直接打到日志中;
  • 如果某个服务器错误(比如服务器挂了),重定向信息也会被写到同一行里;

示例:

1、日志格式

'[$request] | $upstream_addr | $upstream_status | $upstream_response_time s'

2、条件

服务器为:127.0.0.1:3000,访问链接 http://c.test.com/ (本机host已经指向 nginx 服务器),忽略资源带来的日志(每个资源请求也会写入日志),日志结果为:

3、upstream只有一个服务器

[GET / HTTP/1.1] | 127.0.0.1:3000 | 200 | 0.010 s

4、upstream有两个服务器,但是一个服务器挂了(会触发nginx导向另外一个服务器)

[GET / HTTP/1.1] | 185.186.147.210:80, 127.0.0.1:3000 | 502, 200 | 0.287, 0.009 s

说明:

  • 先访问到第一个服务器 185.186.147.210:80,但是因为服务器挂了,报502错误,访问时间是 0.287s;
  • 于是访问另外一个服务器 127.0.0.1:3000,服务器ok,状态码是200,访问时间是 0.009s;

5、以 URL 做区分实现负载均衡

常见场景:

有一个根域名 c.test.com,然后已开发了 c.test.com/a 等多个服务已在线上正常运行。

现需要开发一个新业务,和之前的业务是独立的(即不需要和之前的页面交互),因为解耦原则,因此定该新业务的域名为 c.test.com/b

由于上新业务,当然最好是上新服务器(服务器组)咯。这样避免新业务down了影响老业务,也方便管理和开发。

因此,我们要实现以下效果

  • 访问 c.test.com/a ,由 x.x.x.1 服务器(服务器组)处理;
  • 访问 c.test.com/b ,由 x.x.x.2 服务器(服务器组)处理;
  • x.x.x.2 服务器在处理 url 的时候,不考虑 /b。例如,当访问 /a/abc 的时候,服务器只匹配 /abc,这样做的原因是好处很多,略;

实现方法:

1、先配置两组服务器的服务器池:

x.x.x.1 服务器(服务器组,记为my_server_list_a),如下配置。(这里的IP地址是可用的,指向我自己的服务器,下同)

upstream my_server_list_a{server 185.186.147.210;
}

x.x.x.2 服务器(服务器组,记为my_server_list_b),如下配置。

upstream my_server_list_b{server 103.94.185.215:3000;
}

2、根据 url 来配置 server:

server {listen 80;# 监听的域名是 c.test.com,即用户访问 c.test.com 时,触发这个配置server_name c.test.com;# 访问 c.test.com/a 时触发这个逻辑location /a/ {# 反向代理到 my_server_list_a 池中,记得最后一定要加斜杠 /proxy_pass http://my_server_list_a/;#            proxy_set_header X-Forwarded-For $remote_addr;}# 访问 c.test.com/b 时触发这个逻辑location /b/ {# 反向代理到 my_server_list_b 池中proxy_pass http://my_server_list_b/;#            proxy_set_header X-Forwarded-For $remote_addr;}
}

3、done,搞定了。

4、唯一需要注意的是,前端页面在写路径时(例如css文件 style.css 位于服务器 b 的根路径下),不能写绝对路径 /style.css,而是要写相对路径 ./style.css 才可以。

5、类似的情况有:【各种资源文件】、【异步请求】等,都需要写相对路径。

6、解决方案:将静态资源和页面解耦,页面放在服务器下,而静态资源放在CDN下,在页面中写成绝对路径。当 URL 匹配时,后端服务器只返回符合要求的静态页面,静态页面自己去找路径符合的静态资源。(我在阿里时,就是这么实现的)

6、双机高可用

原因:

一个nginx服务器作为入口,如果nginx服务器挂了,后面服务将全部不可用。

解决办法:

一台服务器不够,那就上两台。但是两台nginx服务器怎么运作呢?

6.1、方法一:一主一备份

原理解释:

  • 两个服务器,分别称为主服务器和备份服务器,两个在同一个网关下(必须);
  • 使用虚拟IP技术,两台服务器都指向这一个虚拟IP;
  • 初始情况下,主服务器生效(虚拟IP指向主服务器),流量全部走主服务器;
  • 当主服务器挂了(注意,是服务器挂了,而不是nginx服务挂了),备份服务器自动顶上去(即此时虚拟IP指向备份服务器);
  • 效果:主服务器即使挂了,备份服务器也能在几秒钟后接管;
  • 这种虚拟IP从主服务器指向备份服务器的过程,叫做【IP漂移】;

实现方法:

首先你要有一台主服务器,然后配置虚拟IP。

虚拟IP的实现方法,是让一台服务器指向多个IP,参考我之前写的那篇文章:05、一个nginx服务器为多个ip服务.md

假如主服务器的 IP 是 192.168.1.11,备份服务器的 IP 是 192.168.1.12

配置虚拟IP,让主服务器和备份服务器的虚拟 IP ,都指向 192.168.1.100(先配主服务器的)。

注:制造备份服务器的简单解决办法,是先配置好主服务器,然后复制一份创建备份服务器(比如虚拟机,可以直接克隆一份)

此时访问 192.168.1.100,会自动访问主服务器。

此时手动挂掉主服务器(比如直接关机),然后再访问 192.168.1.100,有几秒无响应,过后会自动由备份服务器接管。

6.2、方法二:利用 Keepalived 双机同存

  • 方法一中,入口只有一个虚拟IP,他只会指向其中一个nginx服务器,除非这个服务器挂了,或者手动漂移到另外一个服务器,否则虚拟IP不会指向另外一个服务器;
  • 而方法二,利用 Keepalived,可以自动切换虚拟IP指向的服务器,当服务器down了,或者nginx服务挂了,也会自动自动切换;

实现方法我给一个参考链接吧:https://www.jianshu.com/p/da26df4f7d60

7、更多nginx内容,请查看我的github

https://github.com/qq20004604/nginx-demo
如果方便,麻烦给一个star,谢谢

利用Nginx实现负载均衡(反向代理)完全详解相关推荐

  1. Nginx安装/负载均衡/反向代理配置与调优

    [Nginx安装] Linux下直接使用包管理安装 sudo apt-get install nginx 使用whereis命令查看安装位置 whereis nginx #sbin下代表nginx可执 ...

  2. Linux中 Nginx+uwsgi部署flask项目 Nginx负载均衡 反向代理

    Nginx是一款自由的.开源的.高性能HTTP服务器和反向代理服务器. 轻量级,同样起web服务,比 apache占用更少的内存及资源 抗并发, nginx处理请求是异步非阻塞的,而 apache则是 ...

  3. day10 负载均衡反向代理

    day10 负载均衡反向代理 1.复习 1.nginx+python的流程1.1安装基础环境yum install python3 pip3 install django==2.2.2安装uwsgi之 ...

  4. 利用nginx+lua+redis实现反向代理方法教程

    这篇文章主要给大家介绍了利用nginx+lua+redis实现反向代理方法教程,文中介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧. 前言 最近因为工作需要,要进行IVR的 ...

  5. Nginx反向代理配置详解

    Nginx反向代理配置详解 Nginx简单的反向代理配置,包括配置文件中各项参数的的注释,好了,开始! 开始首先安装Nginx 一.建立用户和用户组 1 2 ./usr/sbin/groupadd w ...

  6. Java开源生鲜电商平台-Java分布式以及负载均衡架构与设计详解(源码可下载)

    Java开源生鲜电商平台-Java分布式以及负载均衡架构与设计详解(源码可下载) 说明:主要是针对一些中大型的项目需要进行分布式以及负载均衡的架构提一些思路与建议. 面对大量用户访问.高并发请求,海量 ...

  7. IIS负载均衡-Application Request Route详解第一篇: ARR介绍

    IIS负载均衡-Application Request Route详解第一篇: ARR介绍   说到负载均衡,相信大家已经不再陌生了,本系列主要介绍在IIS中可以采用的负载均衡的软件:微软的Appli ...

  8. 负载均衡原理与实践详解 第五篇 负载均衡时数据包流程详解

    负载均衡原理与实践详解 第五篇 负载均衡时数据包流程详解 系列文章: 负载均衡详解第一篇:负载均衡的需求 负载均衡详解第二篇:服务器负载均衡的基本概念-网络基础 负载均衡详解第三篇:服务器负载均衡的基 ...

  9. IIS负载均衡-Application Request Route详解第三篇:使用ARR进行Http请求的负载均衡(上)...

    IIS负载均衡-Application Request Route详解第三篇:使用ARR进行Http请求的负载均衡(上) 在前两篇文章中,我们已经讲述如何配置与安装ARR,从本篇文章开始,我们将重点的 ...

  10. IIS负载均衡-Application Request Route详解第六篇:使用失败请求跟踪规则来诊断ARR

    失败请求跟踪规则(FailedRequest Tracing Rules)是IIS7中对请求处理进行诊断的强大的工具.我们本篇文章将会带领大家一步步的来配置失败请求跟踪规则,并且告诉大家如何使用这些信 ...

最新文章

  1. 406. Queue Reconstruction by Height
  2. HOOK技术-满足我们程序的偷窥欲
  3. C语言中的struct和union区别
  4. spgridview的过滤功能回调时发生错误~
  5. 系统建模、分析、仿真和验证软件工具ModelCodoer
  6. 26产品经理需要具备的市场观察能力
  7. ORB_SLAM : semi dense code
  8. 学习用 Keras 搭建 CNN RNN 等常用神经网络
  9. Android插件框架VirtualAPK学习和使用
  10. paip.语义分析--单字动词表.txt
  11. python 设置请求时间间隔_如何自学Python爬虫?新手入门教程
  12. mro python_Python之super与MRO
  13. Consider defining a bean of type ‘com.xingchen.media.service.MediaFileService‘ in your configuration
  14. 数据库工具sqlDBx连接mysql
  15. 打开文件安全警告怎么关闭?
  16. Android项目工程结构介绍
  17. 数据链路层的子层MAC层(图文详解)
  18. linux内核使用scons构建,使用scons软件构建工具
  19. Android 信号查看,安卓Android手机怎么快速查看系统信号强度
  20. 【持续更新】SDN Software Defined Networks(Thomas D.Nadeau Ken Gray)翻译

热门文章

  1. 埃森哲推出软件许可证管理区块链平台
  2. 四川轻化工大学计算机网络技求术,四川轻化工大学
  3. Python 使用openpyxl读取excel字体颜色与单元格颜色
  4. 有哪些软件可以替代Adobe系列
  5. mac与windows键盘对应表
  6. 苏州大学计算机学院保研条件,2018年苏州大学保研推免接收办法
  7. ConvNets Principles
  8. 手机端微信一键登录插件代码分享
  9. 数据分析模板一赛题分析(预测房屋租金)
  10. 如何做移动O2O产品的运营推广