专栏:Nginx实战进阶指南
说明:后续会在这个专栏上分享大量实战生产经验,实现由浅入深,逐步分析,每个项目上都带有实战内容,整个包括部署,实战,优化经验,以及各种疑难杂症和面试经验,如果您是初学者,请订阅专栏,以便接收最新文章。
负载均衡:(Load Balance),意思是将负载(工作任务,访问请求)进行平衡、分摊到多个操作单元(服务器,组件)上进行执行。是解决高性能,单点故障(高可用),扩展性(水平伸缩)的解决方案。nginx的负载均衡功能是建立在反向代理之上的。
文章目录
一、代理服务
1.1 理解正向代理与用途
正向代理概念:是一个位于客户端和目标服务器之间的服务器(代理服务器),为了从目标服务器取得内容,客户端向代理服务器发送一个请求并指定目标,然后代理服务器向目标服务器转交请求并将获得的内容返回给客户端。
即:正向代理即是客户端代理, 代理客户端, 服务端不知道实际发起请求的客户端.
1.1.1 正向代理案例:
- 例如家庭宽带,翻墙上网
- 突破访问限制,浏览外部新闻,需要翻墙上网
- 隐藏客户端真实IP,对服务端来讲,收到的请求源IP是代理IP
1.2 理解反向代理与用途
反向代理概念:是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
即:反向代理即是服务端代理, 代理服务端, 客户端不知道实际提供服务的服务端
1.2.1 反向代理实例:
- 负载均衡服务,保障后端均衡提供服务,反向代理服务器可以做负载均衡,根据所有真实服务器的负载情况,将客户端请求分发到不同的真实服务器上。
- 缓存服务, 反向代理服务器可以对于静态内容及短时间内有大量访问请求的动态内容提供缓存服务,提高访问速度
- 保护后端服务,反向代理服务器可以作为应用层防火墙,为网站提供对基于Web的攻击行为(例如DoS/DDoS)的防护,更容易排查恶意软件等,比如在代理层禁掉不合理的请求,大量的爬虫请求。
二、Nginx作为反向代理与负载均衡服务
2.1 作为负载均衡服务器
负载均衡:(Load Balance),意思是将负载(工作任务,访问请求)进行平衡、分摊到多个操作单元(服务器,组件)上进行执行。是解决高性能,单点故障(高可用),扩展性(水平伸缩)的解决方案。nginx的负载均衡功能是建立在反向代理之上的。
SLB(服务器负载均衡):在多个提供相同服务的服务器的情况下,负载均衡设备存在虚拟服务地址,当大量客户端从外部访问虚拟服务IP地址时,负载均衡设备将这些报文请求根据负载均衡算法,将流量均衡的分配给后台服务器以平衡各个服务器的负载压力,避免在还有服务器压力较小情况下其他服务达到性能临界点出现运行缓慢甚至宕机情况,从而提高服务效率和质量。
因此对客户端而言,RS(real server 实际服务器)的IP地址即是负载均衡设备VIP(虚拟服务地址IP)地址,真正的RS服务器IP地址对于客户端是不可见的。
2.1.1 负载均衡示例:
- 银行与医院的取号机
- 地铁人肉导流
2.1.2 负载均衡与反向代理的区别
反向代理和负载均衡这两个词经常出现在一起,但他们实际上是不同的概念,负载均衡它更多的是强调的是一种算法或策略,将请求分布到不同的机器上,因此实际上也起到了反向代理的作用。
反向代理分为四层和七层,如果是七层的反向代理,比如代理到一个域名上,则负载均衡的功能只能是域名解析来做,或代理到一组upstream池上,具体的负载均衡情况,交给upstream的负载均衡策略来做。如果是四层的反向代理,则可以代理到多台机器上,具体的负载均衡情况,也是交给upstream的负载均衡策略来做。
2.2 【案例】七层负载均衡
业务需求:将www.51xuesql.com请求均衡到不同的后端机器上,后端机器转发到服务处理机器上。
2.2.1 逻辑架构图:
2.2.2 基础配置:
nginx.conf下调整如下配置:
.....
log_format main '[$time_local] [$remote_addr] [$COOKIE_userid] [$request] [$status]
[$body_bytes_sent] [$http_referer] [$http_user_agent]
[$http_x_forwarded_for] [$request_time] [$upstream_addr]
[$upstream_response_time] [$http_host] [$request_body] [$uri]
[$server_port] [$remote_user] [-]';
.....
include vhosts/*.conf;
2.2.3 前端代理层配置
upstream 51xuebak {
server 192.168.10.52 weight=1 max_fails=2 fail_timeout=5s;
server 192.168.10.53 weight=1 max_fails=2 fail_timeout=5s;
}
server {
listen 80;
server_name www.51xuesql.com;
access_log logs/51xuesql.access.log main;
error_log logs/51xuesql.error.log;
index index.html index.php index.htm;
root /usr/local/nginx/;
location / {
root /usr/local/nginx/html/;
index index.html index.php index.htm;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header Access-Control-Allow-Origin *;
charset utf-8;
proxy_set_header Host $host;
proxy_pass http://51xuebak;
}
}
2.2.4 后端业务层配置:
server {
server_name www.51xuesql.com;
access_log logs/51xuesql.access.log main;
error_log logs/51xuesql.error.log;
index index.html index.php index.htm;
root /usr/local/nginx/;
location / {
root html;
index index.html index.htm;
}
}
2.2.5 后端业务层首页:
/usr/local/nginx/html/index.html
<h1>backend 51xue 52</h1>
<h1>backend 51xue 53</h1>
2.2.6 反向代理验证
2.2 作为反向代理服务器
主要应用与网关转发,将接收到的请求转发到后端具体服务上。
表现为:
- 网关端口转发
- 业务逻辑转发
备注:我们将已一个案例的方式验证反向代理,(第三节内容)
三 [案例]开源中小企业sql审核利器
3.1 Yearning 介绍:
Yearning 面向中小型企业的轻量级MySQL SQL语句审核平台.提供查询审计,SQL审核等多种功能.目前已经支持多种DB的管理。
还有一个开源工具叫做Archery,他的部署稍微优点复杂,但功能更为齐全。
生产环境如果DB不多的话,十来个数据库可以使用Yearning,再多的话建议还是使用Archery工具。
3.2 服务部署内容:
3.2.1 下载解压
wget https://github.com/cookieY/Yearning/releases/download/2.3.2.1/Yearning-2.3.2.2-linux-amd64.zip
mkdir /usr/local/yearning && cd /usr/local/yearning
unzip Yearning-2.3.2.2-linux-amd64.zip
3.2.2 修改配置
cat conf.toml
[Mysql]
Db = "Yearning"
Host = "127.0.0.1"
Port = "3306"
Password = "xxxx"
User = "root"
[General] #数据库加解密key,只可更改一次。
SecretKey = "dbcjqheupqjsuwsm"
3.2.3 数据库权限:
create database Yearning;
#grant select,delete,update,insert on Yearning.* to yearning@127.0.0.1 identified by '51xuesql';
flush privileges;
3.2.4 启动服务:
./Yearning --help
./Yearning install
nohup ./Yearning run &
打开浏览器 http://127.0.0.1:8000
默认账号/密码:admin/Yearning_admin
3.2.5 后端配置转发:
备注:去掉默认根匹配,增加如下配置
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header Access-Control-Allow-Origin *;
charset utf-8;
proxy_set_header Host $host;
proxy_pass http://192.168.10.53:8000;
}
3.2.6 Yearnning使用说明
具体详细内容,我们不再章节中说明,只请参考文档,这里面会有详细的说明。
参考文档:Yearning: Yearning Mysql SQL审核平台 (gitee.com)
四 了解两个内容
4.1 了解负载均衡策略
- 轮询(Round Robin):顺序循环将请求一次顺序循环地连接每个服务器。当其中某个服务器发生第二到第7 层的故障,BIG-IP 就把其从顺序循环队列中拿出,不参加下一次的轮询,直到其恢复正常。
- 权重(weight):给每个服务器分配一个加权值为比例,根椐这个比例,把用户的请求分配到每个服务器。当其中某个服务器发生第二到第7 层的故障,BIG-IP 就把其从服务器队列中拿出,不参加下一次的用户请求的分配, 直到其恢复正常。
4.2 了解proxy_pass的配置参数
- proxy_set_header Host $host;
设置访问具体的header地址,指定header问$host,即访问的域名。
若转发的后端有多个域名,公用80端口,不设置header地址的话,会访问失败,不知道具体访问那个域名。
- proxy_pass http://51xue_backend;
代理有两种方式,一种是四层代理,通过具体的IP地址,另外一种是七层代理,通过具体的域名服务。
代理后端的具体地址,七层必须有“http://”字段,四层代理直接写ip地址即可。
五 负载均衡上一些思考
负载均衡分类:https://mp.weixin.qq.com/s/E4n_h1FS_oKXXZsQNWQRJQ
5.1 Dns作为负载均衡
查看“网站的访问流程”
DNS 实现负载均衡是最基础简单的方式。一个域名通过 DNS 解析到多个 IP,每个 IP 对应不同的服务器实例,这样就完成了流量的调度,虽然没有使用常规的负载均衡器,但实现了简单的负载均衡功能。
通过 DNS 实现负载均衡的方式,最大的优点就是实现简单,成本低,无需自己开发或维护负载均衡设备,不过存在一些缺点:
- 服务器故障切换延迟大,服务器升级不方便。我们知道 DNS 与用户之间是层层的缓存,即便是在故障发生时及时通过 DNS 修改或摘除故障服务器,但中间经过运营商的 DNS 缓存,且缓存很有可能不遵循 TTL 规则,导致 DNS 生效时间变得非常缓慢,有时候一天后还会有些许的请求流量。
- 流量调度不均衡,粒度太粗。DNS 调度的均衡性,受地区运营商 LocalDNS 返回 IP 列表的策略有关系,有的运营商并不会轮询返回多个不同的 IP 地址。另外,某个运营商 LocalDNS 背后服务了多少用户,这也会构成流量调度不均的重要因素。
- 流量分配策略太简单,支持的算法太少。DNS 一般只支持 rr 的轮询方式,流量分配策略比较简单,不支持权重、Hash 等调度算法。
- DNS 支持的 IP 列表有限制。我们知道 DNS 使用 UDP 报文进行信息传递,每个 UDP 报文大小受链路的 MTU 限制,所以报文中存储的 IP 地址数量也是非常有限的,阿里 DNS 系统针对同一个域名支持配置 10 个不同的 IP 地址。
实际上生产环境中很少使用这种方式来实现负载均衡,毕竟缺点很明显。文中之所以描述 DNS 负载均衡方式,是为了能够更清楚地解释负载均衡的概念。
像 BAT 体量的公司一般会利用 DNS 来实现地理级别的全局负载均衡,实现就近访问,提高访问速度,这种方式一般是入口流量的基础负载均衡,下层会有更专业的负载均衡设备实现的负载架构。
这就是即使在dns解析了,也要设置业务统一入口层,然后再才有软件负载均衡到具体业务。
5.2 软件负载均衡
软件负载均衡,可以在普通的服务器上运行负载均衡软件,实现负载均衡功能。目前常见的有 Nginx、HAproxy、LVS。其中的区别:
- Nginx:七层负载均衡,支持 HTTP、E-mail 协议,同时也支持 4 层负载均衡;
- HAproxy:支持七层规则的,性能也很不错。OpenStack 默认使用的负载均衡软件就是 HAproxy;
- LVS:运行在内核态,性能是软件负载均衡中最高的,严格来说工作在三层,所以更通用一些,适用各种应用服务。
软件负载均衡的优点:
- 易操作:无论是部署还是维护都相对比较简单;
- 便宜:只需要服务器的成本,软件是免费的;
- 灵活:4 层和 7 层负载均衡可以根据业务特点进行选择,方便进行扩展和定制功能。
六、 思考一些问题:
6.1 架构图中有什么问题?
只有一台代理机器
6.2 为什么代理机器可以很少,而后端处理机器不可以很少?
代理机器只是负责转发,拿到请求,根据规则找到下一跳,将请求丢过去就好了,支持并发操作,不涉及cpu密集计算,不涉及磁盘IO密集处理。仅需要轻量级的cpu计算,少量的IO,基本数据都在缓存中,响应会很快。
6.3 后端出现问题,该不该手动切下线?
6.3.1 问题分析说明
使用负载均衡的时候,转发到后端是多个节点。
upstream 51xuebak {
server 192.168.10.52 weight=1 max_fails=2 fail_timeout=5s;
server 192.168.10.53 weight=1 max_fails=2 fail_timeout=5s;
}
我们这里已经使用了max_fails
和fail_timeout
参数来处理失败的情况。这意味着Nginx会自动处理这些服务器的故障转移。
具体来说:
max_fails=2
指定的是在一个给定的时间窗口内(默认10秒),如果一个服务器连续失败两次,则会被标记为不可用。fail_timeout=5s
表示如果一个服务器被标记为不可用,则会在5秒内不会接收新的请求。
当192.168.10.52出现故障时,Nginx 会根据上述设置自动将它从负载均衡池中移除,并在fail_timeout
设定的时间之后尝试重新检查该服务器的状态。如果服务器恢复正常,则会自动将其重新加入到负载均衡池中。
因此,在大多数情况下,你不需要手动从配置中删除该节点。Nginx 会自动处理这些情况。如果你确定该服务器永久性地不再提供服务,或者你需要进行一些维护操作,那么才需要手动修改配置文件以删除该节点,并重启 Nginx 使更改生效。
6.3.2 产生的问题
上述的配置,看着好像很智能,能够基于一定的时间内判断服务是否正常,但是在这个时间段内,依然会有大量的请求失败,并且,网关需要定期去探活,需要判断后端服务是否正常了,因此,每次探活时间,都是需要引入生产流量,对正常流量造成一点影响。
注意:千万不要想着,业务有重试功能,也就慢个几秒罢了,并且即使有部分请求有问题,问题也不大的。当你面对的业务是特别敏感的(交易,订单),影响公司的收入(只要是跟钱挂钩的)都是大问题,这里一定要切记,自己执行的标准高一点,服务的能力才会高一点,其它业务方的配合的标准度也会高。
6.3.3 生产环境建议
- 并分较低,业务不敏感:可以依赖服务自身的配置进行故障转移。
- 并发量较高,业务敏感:一定要到网关处进行下线该站点,对该站点增加注释,重新reload服务即可。