CDN调度器HAProxy、Nginx、Varnish
CDN功能如下:
1、将全网IP分为若干个IP段组,分组的依据通常是运营商或者地域,目的是让相同网络环境中的用户聚集到相同的组内;
2、依据CDN服务器们的网络和容量,确定哪些CDN服务器适合服务哪些IP段组;
3、根据以上两步得到的结论,让用户去最适合他的服务器得到服务。
说白了,就是根据用户不同的来源IP把用户请求重定向到不同的CDN服务器上去。
那么,如何实现呢?
智能DNS是办法之一,稳定可靠且有效。
但至少在两个环境下它不能完全满足我们:
1、需要特别精细的调度时。由于大多数DNS Server不支持DNS扩展协议,所以拿不到用户的真实IP,只能根据Local DNS来调度。
2、访问特别频繁时。由于每次调度都将触发一次DNS,如果请求变得密集,DNS请求本身带来的开销也会相应变大;
3、需要根据服务器的带宽容量、连接数、负载情况、当机与否来调度时。由于DNS Server没有CDN节点服务器的信息,这种调度会变得困难。
这时候我们可以:
1、将用户先行引导到某一台或几台统一的服务器上去;
2、让它拿到用户的真实IP,计算出服务他的服务器;
3、通过HTTP302或其它方式把用户定位到最终服务器上。
部署在用户先访问到的那几台服务器上,负责定位IP然后重定向用户请求的那个软件,我们叫它“调度器”。
HAProxy实现:
HAProxy不支持形如0.0.0.1-0.8.255.255 cn的IP段表示方法,只支持1.1.4.0/22 “CN”的IP段表示方法。
1、我们需要先把IP段转化成它认识的方式;
a> 下载iprang.c或者iprang.c本地镜像;
b> 编译gcc -s -O3 -o iprange iprange.c;
c> 整理IP段列表geo.txt形如:
1
2
3
4
5
6
7
8
9
10
11
|
# head geo.txt
"1.0.0.0"
,
"1.0.0.255"
,
"AU"
"1.0.1.0"
,
"1.0.3.255"
,
"CN"
"1.0.4.0"
,
"1.0.7.255"
,
"AU"
"1.0.8.0"
,
"1.0.15.255"
,
"CN"
"1.0.16.0"
,
"1.0.31.255"
,
"JP"
"1.0.32.0"
,
"1.0.63.255"
,
"CN"
"1.0.64.0"
,
"1.0.127.255"
,
"JP"
"1.0.128.0"
,
"1.0.255.255"
,
"TH"
"1.1.0.0"
,
"1.1.0.255"
,
"CN"
"1.1.1.0"
,
"1.1.1.255"
,
"AU"
|
d> 输出HAProxy认识的IP段列表:
1
2
3
4
5
6
7
8
9
10
11
12
|
# cut -d, -f1,2,5 geo.txt | ./iprange | head
1.0.0.0
/
24
"AU"
1.0.1.0
/
24
"CN"
1.0.2.0
/
23
"CN"
1.0.4.0
/
22
"AU"
1.0.8.0
/
21
"CN"
1.0.16.0
/
20
"JP"
1.0.32.0
/
19
"CN"
1.0.64.0
/
18
"JP"
1.0.128.0
/
17
"TH"
1.1.0.0
/
24
"CN"
1.1.1.0
/
24
"AU"
|
e> 便于管理的目的,将整合后的IP段归类到同一个文件中:
1
2
3
4
5
6
7
|
# cut -d, -f1,2,5 geo.txt | ./iprange | sed 's/"//g' | awk -F' ' '{ print $1 >> $2".subnets" }'
# ls *.subnets
A1
.
subnets
AX
.
subnets
BW
.
subnets
CX
.
subnets
FJ
.
subnets
GR
.
subnets
IR
.
subnets
LA
.
subnets
ML
.
subnets
NF
.
subnets
PR
.
subnets
SI
.
subnets
TK
.
subnets
VE
.
subnets
# cat AU.subnets
1.0.0.0
/
24
1.0.4.0
/
22
1.1.1.0
/
24
|
f> 把这些文件放到同一个文件夹下,我们以/etc/haproxy/conf/为例。
2、正确配置HAProxy以这些IP段为规则正确调度;
下面是一个haproxy.cfg的例子。配置好后重启Haproxy即可。
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
global
log
127.0.0.1
local2
debug
chroot
/
var
/
lib
/
haproxy
pidfile
/
var
/
run
/
haproxy
.
pid
maxconn
8000
user
haproxy
group
haproxy
daemon
stats
socket
/
var
/
lib
/
haproxy
/
stats
defaults
mode
http
log
global
option
httplog
option
dontlognull
option
http
-
server
-
close
option
forwardfor
except
127.0.0.0
/
8
option
redispatch
retries
3
timeout
http
-
request
10s
timeout
queue
1m
timeout
connect
10s
timeout
client
1m
timeout
server
1m
timeout
http
-
keep
-
alive
10s
timeout
check
10s
maxconn
8000
frontend
main *
:
5000
acl
geo_A1
src
-
f
/
etc
/
haproxy
/
conf
/
A1
.
subnets
acl
geo_AX
src
-
f
/
etc
/
haproxy
/
conf
/
AX
.
subnets
acl
geo_BW
src
-
f
/
etc
/
haproxy
/
conf
/
BW
.
subnets
acl
geo_CX
src
-
f
/
etc
/
haproxy
/
conf
/
CX
.
subnets
acl
geo_FJ
src
-
f
/
etc
/
haproxy
/
conf
/
FJ
.
subnets
.
.
.
reqrep
^
(
[
^
\
]
*
)
\
/
(
.
*
)
\
HTTP
\
1
\
/
\
2
&
ipfrom
=
A1
\
HTTP
if
geo_A1
reqrep
^
(
[
^
\
]
*
)
\
/
(
.
*
)
\
HTTP
\
1
\
/
\
2
&
ipfrom
=
AX
\
HTTP
if
geo_AX
reqrep
^
(
[
^
\
]
*
)
\
/
(
.
*
)
\
HTTP
\
1
\
/
\
2
&
ipfrom
=
BW
\
HTTP
if
geo_BW
reqrep
^
(
[
^
\
]
*
)
\
/
(
.
*
)
\
HTTP
\
1
\
/
\
2
&
ipfrom
=
CX
\
HTTP
if
geo_CX
reqrep
^
(
[
^
\
]
*
)
\
/
(
.
*
)
\
HTTP
\
1
\
/
\
2
&
ipfrom
=
FJ
\
HTTP
if
geo
_FJ
.
.
.
default_backend
static
backend
static
server
static
127.0.0.1
:
6081
check
|
Nginx实现:
Nginx可以在核心模块HttpGeoModule(http://wiki.nginx.org/HttpGeoModule)的配合下实现调度:
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
32
33
34
35
36
37
38
39
40
41
|
http
{
.
.
.
geo
$
useriprang
{
ranges
;
default
a
;
0.0.0.1
-
0.8.255.255
a
;
0.9.0.0
-
0.255.255.255
a
;
1.0.0.0
-
1.0.0.255
a
;
1.0.1.0
-
1.0.1.255
b
;
1.0.2.0
-
1.0.3.255
b
;
1.0.4.0
-
1.0.7.255
a
;
.
.
.
223.255.252.0
-
223.255.253.255
c
;
223.255.254.0
-
223.255.254.255
a
;
223.255.255.0
-
223.255.255.255
a
;
}
upstream
backend
{
server
127.0.0.1
:
81
;
}
server
{
listen
80
;
client_max_body
_size
10240m
;
location
/
{
proxy_redirect
off
;
proxy_pass
http
:
//backend$request_uri&useriprang=$useriprang;
proxy_next_upstream
http_502
http_504
error
timeout
invalid_header
;
proxy_cache
cache_one
;
proxy_cache
_key
$
host
:
$
server_port
$
uri
$
is_args
$
args
;
expires
5s
;
}
}
.
.
.
}
|
Varnish实现:
Varnish则有两个插件可以实现调度:
https://github.com/cosimo/varnish-geoip (Last updated: 28/05/2013)
https://github.com/meetup/varnish-geoip-plugin (Last updated: 2010)
性能问题
如上所述,使用Haproxy、Nginx、Varnish都能快速实现这个功能。
其中Nginx和Varnish使用了二分法在IP表中定位用户IP,而Haproxy是逐条过滤。
所以在IP分得较细,IP段组较多(归类后超过1000组)时,Haproxy会出现明显的性能衰减,其余两者没有这个问题。
其它
本文使用的软件版本如下:
HAProxy1.4.22,Nginx1.2.9,Varnish3.0.4。
HAProxy和Varnish都是目前的最新版本。
本文有参考http://blog.exceliance.fr/2012/07/02/use-geoip-database-within-haproxy/
转自:http://blog.yikuyiku.com/?p=3851
成长的对话版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!