记一次Nginx负载均衡

前因

今天收到客服反馈很多用户说播放视频卡,甚至无法播放,检查后发现分布式存储系统里的某台服务器带宽满了,而导致带宽突然跑满的原因是由于某视频爆火,带宽一下子增加了3G。

过程

架构图

简单说下这块的访问流程:当用户访问 http://file.example.com/a.mp4 ,根据DNS解析,这个请求会先到达调度器(100.0.0.1),调度器经过数据库查询,得知这个文件存储在存储服务器1(200.0.0.1)上,然后会给用户返回一个302,把地址指向到 http://200.0.0.1/file.example.com/a.mp4 ,用户请求302后的地址,即得到了资源。

服务器物理带宽跑满,那没其他办法了,只能把带宽调度均摊到其他服务器上。这就有一个问题了,调度器给的地址,是以IP开头的地址,而要修改调度器的话,就要去改数据库了,这个不是一个规范的操作,而且是个危险的操作,所以这个方案直接排除。调度器这块不能更改,那只能从存储服务器1上动手了,当用户访问302后的地址也就是 http://200.0.0.1/file.example.com/a.mp4 时,实际上访问的是Nginx的80端口,这就有文章可以做了,下面是具体思路。

存储1(高流量):当收到用户请求时,先在Nginx里对请求做一个处理,将60%的流量302到存储2和存储3的8080端口,同时新开放一个81端口,用于存储2以及存储3服务器的回源。
存储2、存储3(低流量):安装OCT软件(一个内容缓存服务,类似squid服务),从存储1的81端口进行缓存资源,OCT开放8080端口。

下面是存储1的Nginx配置文件,在对应的location里添加了lua代码,这个是这个架构的核心所在。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
server {
listen 80 default_server;
#新增81端口用于存储2以及存储3用于回源
listen 81 default_server;
charset utf-8;
server_name 200.0.0.1;

location ~ "^/\d{1,2}/" {

#下面这段lua代码是核心,将用户请求中的60%流量进行302重定向,返回一个存储2以及存储3服务器上带8080端口的URL

rewrite_by_lua '
if ngx.var.server_port == "81" then
return
end

x = math.random()
if x > 0.4 and x <= 0.7 then
ngx.redirect("http://200.0.0.2:8080" .. ngx.var.request_uri)
return
end

if x > 0.7 then
ngx.redirect("http://200.0.0.3:8080" .. ngx.var.request_uri)
return
end
';
}

}

存储2以及存储3上OCT的配置文件则如下:

1
2
3
4
5
6
7
8
9
10
11
threads 4 #4线程
store ssd #存储组名叫ssd
path /dev/sdb #ssd对应的快设备(硬盘)

listen 8080 #监听8080端口
description stf #备注
upstream_host 200.0.0.1:81 #从存储1的81端口进行回源
expires_default 6000000 #默认过期时间,单位秒
order_of_store ssd #缓存存在名叫ssd的存储组上
check_consistency on #开启一致性检查
mp4 mp4|flv start end second #对视频文件开启拖拽支持

配置文件配置好后,分别重载服务,即可生效。此时用户再来访问 http://file.example.com/a.mp4 ,那过程就是先到调度器,调度器302到 http://200.0.0.1/file.example.com/a.mp4 ,而后面有60%的概率再返回一个302,将用户302到 http://200.0.0.2:8080/file.example.com/a.mp4

结果

原来流量跑满的服务器,流量成功降了下来,而低流量的服务器,流量瞬间上升,客服回访用户,均恢复正常。

作者

Frog Rain

发布于

2018-09-09

更新于

2025-04-08

许可协议