- 论坛徽章:
- 0
|
ISP级别的,支持海量域名的dns架构
--基于mysql的dns服务器
[首发:http://www.opensolution.org.cn/?p=241,有任何问题欢迎到www.opensolution.org.cn进行讨论]
------------------------------------------------------------------------
1. 缘起
2. 方案选择
3. 框架结构
4. 安装配置
4.1. 首先安装mysql(不然bind找不到mysql,无法安装mysql的dlz插件)
4.1.1. 创建OS帐号
4.1.2. 目录结构准备
4.1.3. 编译安装源码
4.1.4. 启动
4.2. 安装bind
4.2.1. 创建用户
4.2.2. 创建var目录并修改权限
4.2.3. 编译安装
4.2.4. 修改/etc/init.d/named文件
4.2.5. named.conf配置
5. 可扩展性
6. 使用现状
------------------------------------------------------------------------
12/12/2008
环境
操作系统: Redhat 5.2 64位
dns服务器:bind9.5.0-p1
数据库: mysql5.1
1. 缘起
=======
公司前些年成为了域名注册商,起初采用一个zone文件存放一个zone配置的传统方式。后了解zone的增长量将会非常大,在n个百万级。在进行了测试和使用一段时间后,发现当zone数量巨大的情况下,采用传统的zone文件存放zone配置,存在着很大的问题。如将所有域名都放在同一服务器上,在需要重新启动bind时,花费的时间惊人,从下图看出当zone的数量达到30万时,载入时间已经需要近1小时,这显然是不能接受的
![]()
后经过权衡,决定以10万为分界,毎10万域名使用一主一辅2台服务器。这种结构尽管有一些不方便,但因为传统的方式稳定性好、查询效率高,所以也用了一段时间。然而当zone的数量到了60多万时,服务器达到了14台,终于觉得不能容忍这种方式了,因为一、太浪费服务器了,二、管理非常不方便,于是乎决心寻找替代的方案
2. 方案选择
===========
在查找一些资料之后,毋庸置疑,基于bind的DLZ(dynamic load zone)是首选。但在DLZ支持的诸多后台数据库中,并不是起初就选择mysql的。bind的查询效率可以达到2万~3万每秒,在DLZ官方,性能评测只有Berkerly DB的查询效率可以达到4000至12000 bps每秒,比较接近bind的原始查询效率,而其他的mysql什么的都只有600~800每秒,Berkerly DB的优势非常明显,因此起初试图使用Berkerly DB作为后台数据库,但最终还是选择了mysql,主要原因如下:
- 使用Berkerly DB的资料非常少
- 使用Berkerly DB不支持类似mysql的sql语句,而仅仅支持api接口,测试和使用门槛比较高
- 没有熟悉Berkerly DB的人员支持,而mysql有同部门的DBA支持
= 性能问题 =
在初步确定采用mysql作为数据库之后,必需要解决查询效率的问题,否则就很难真正投入生产环境。mysql作为后台的查询效率经测试在600-800之间,而我们预期的查询效率必需要达到3k~4k。该结构为什么会慢呢?主要原因就是采用mysql作为后台数据库时,bind不能起用多线程,只能采用单进程。而毎查询一个域名需要执行3~5条sql,所有的sql只能串行处理,所以效率才这么低。解决办法:
- 修改DLZ源码,将单进程改为多线程
该方法经一位熟悉C的同事验证,不可行。(也许CU有大虾能搞定的,那就更方便易行了)
- 在bind和mysql之间加一层cache
在我们的结构中,zone数量非常大,单个域名在短时间被重复查询的几率并不高,分析认为该方法不是特别适合我们的结构,因此未进行测试
- 人造“多线程”
查询效率低的关键原因是串行,因此我们试图人为的实现并行,经过测试后发现可以通过起多个named进程的方式,实现该想法。最终是服务器起8个地址,每个地址单独起一个named。起8个named之后的查询效率如下图,我们可以看出,单个named的查询效率随着named数量的增加从700多降至400,特别是到后期下降趋势很不明显。总体性能从700升至3200左右,两台dns服务器可达到6000多,完全可以满足我们的需要:
![]()
3. 框架结构
===========
这个系统的结构最前端是两台F5的负载均衡设备(这原来就有),后面是两台dns服务器,每台起8个named进程,分别连至后台的mysql数据库。F5的每个vip对应每台dns服务器4个进程,这样整个系统没有任何单点。任何一台设备down了bouquet不影响使用。结构图如下:
![]()
4. 安装配置
===========
4.1. 首先安装mysql(不然bind找不到mysql,无法安装mysql的dlz插件)
=================================================================
4.1.1. 创建OS帐号
=================
#添加mysql组和用户,之所以指定为601,主要是为了方便各台服务器之间权限统一
groupadd -g 601 mysql
useradd -c "mysql software owner" -g mysql -u 601 mysql
4.1.2. 目录结构准备
===================
#编辑自己的配置文件my.cnf和log以及innodb的相关目录
mkdir /usr/local/mysql
mkdir /usr/local/mysql/sock
mkdir /usr/local/mysql/log
su - mysql
mkdir /home/mysql/mysqldata
mkdir /home/mysql/mysqldata/binlog
mkdir /home/mysql/mysqldata/mydata
mkdir /home/mysql/mysqldata/innodb_ts
mkdir /home/mysql/mysqldata/innodb_log
mkdir /home/mysql/mysqldata/tmpdir
exit
mkdir /data
ln -s /home/mysql/mysqldata /data/mysqldata
chown -R mysql:mysql /usr/local/mysql/log
chown -R mysql:mysql /usr/local/mysql/sock
chown -R mysql:mysql /data/mysqldata
chown -R mysql:mysql /data/mysqldata/mydata
chown -R mysql:mysql /data/mysqldata/binlog
chown -R mysql:mysql /data/mysqldata/innodb_ts
chown -R mysql:mysql /data/mysqldata/innodb_log
chown -R mysql:mysql /data/mysqldata/tmpdir
4.1.3. 编译安装源码
===================
make clean
#这里的config参数可以根据数据库相关需求稍作调整
./configure --prefix=/usr/local/mysql \
--without-debug \
--without-bench \
--disable-shared \
--enable-thread-safe-client \
--enable-assembler \
--enable-profiling \
--with-mysqld-ldflags=-all-static \
--with-client-ldflags=-all-static \
--with-charset=latin1 \
--with-extra-charset=utf8,gbk \
--with-innodb \
--with-csv-storage-engine \
--with-federated-storage-engine \
--with-mysqld-user=mysql \
--without-embedded-server \
--with-server-suffix=-community \
--with-unix-socket-path=/usr/local/mysql/sock/mysql.sock \
--with-mysqld-libs=-lmtmalloc \
make
make install
#准备my.cnf文件
需要注意的几个目录配置:
log-error=/usr/local/mysql/log/error.log
log_slow_queries=/usr/local/mysql/log/slow_query.log
datadir=/data/mysqldata/mydata
tmpdir=/data/mysqldata/tmpdir
bin-log=/data/mysqldata/binlog/mysql-bin
innodb_data_home_dir=/data/mysqldata/innodb_ts
innodb_log_group_home_dir=/data/mysqldata/innodb_log
其他相关参数进行针对性调整
将准备好的my.cnf配置文件cp一份到/etc/my.cnf
创建系统表并修改目录权限
cd /usr/local/mysql
bin/mysql_install_db --user=mysql --socket=/usr/local/mysql/sock/mysql.sock
chown -R root .
chgrp -R mysql .
chown -R mysql sock
chown -R mysql log
4.1.4. 启动
===========
bin/mysqld_safe --socket=/usr/local/mysql/sock/mysql.sock --user=mysql &
4.2. 安装bind
=============
4.2.1. 创建用户
===============
useradd -d /etc/namedb -s /bin/false named
4.2.2. 创建var目录并修改权限
============================
mkdir -p /var/named
chown -R named:named /etc/namedb
chown -R named:named /var/named
4.2.3. 编译安装
===============
tar -xzvf bind-9.5.0-p1.tar.gz
./configure --prefix=/opt/named.9.5.0-p1 --sysconfdir=/etc/namedb --with-dlz-mysql=yes --enable-largefile
注:采用mysql做后台数据库,千万不能用--enable-threads选项启用多线程,网上有一些朋友使用mysql做后台,谈到bind会莫名中断服务,大部分都是因为打开了多线程。
4.2.4. 修改/etc/init.d/named文件
================================
关键部分如下:
[ -f /opt/named/sbin/named ] || exit 0
[ -f /etc/namedb/named.conf.11 ] || exit 0
# See how we were called.
case "$1" in
start)
# Start daemons.
echo -n "Starting named: "
daemon /opt/named/sbin/named -c /etc/namedb/named.conf.11 -u named
daemon /opt/named/sbin/named -c /etc/namedb/named.conf.12 -u named
daemon /opt/named/sbin/named -c /etc/namedb/named.conf.13 -u named
daemon /opt/named/sbin/named -c /etc/namedb/named.conf.14 -u named
daemon /opt/named/sbin/named -c /etc/namedb/named.conf.15 -u named
daemon /opt/named/sbin/named -c /etc/namedb/named.conf.16 -u named
daemon /opt/named/sbin/named -c /etc/namedb/named.conf.17 -u named
daemon /opt/named/sbin/named -c /etc/namedb/named.conf.18 -u named
4.2.5. named.conf配置
=====================
关键部分如下,替代了原来对每一个zone的配置:
dlz "Mysql zone" {
database "mysql
{host=localhost dbname=dns user=dns pass=12345678}
{SELECT zone FROM records WHERE zone = '%zone%'}
{SELECT ttl, type, mx_priority, data
FROM records
WHERE zone = '%zone%' AND host = '%record%' AND type <> 'SOA' AND type <> 'NS'}
{SELECT ttl, type, data, primary_ns, resp_contact, serial, refresh, retry, expire, minimum
FROM records
WHERE zone = '%zone%' AND type='NS'}
{SELECT ttl, type, host, mx_priority, data, resp_contact, serial, refresh, retry, expire, minimum
FROM records
WHERE zone = '%zone%' AND type <> 'NS'}";
};
5. 可扩展性
===========
该结构的可扩展性非常好,可采用的方式如下:
- 在单台服务器上增加named的数量
- 增加物理服务器,作为新节点添加到负载均衡设备里
- 增加授权的dns服务器,例如:原授权dns服务器为ns1.test.com,ns2.test.com,我们可将授权dns增加到4台为ns1.test.com,ns2.test.com、ns3.test.com,ns4.test.com,通过在ns3.test.com,ns4.test.com后搭建同样的架构系统,可大大增加系统的查询能力,同时将该架构放置在不同的地理位置,还可以实现dns的灾备、冗余。
- 如果mysql的压力大,也随时可以扩充mysql的节点。分担mysql的压力。
6. 使用现状
===========
目前dns上的zone数量为约90万,查询速率为500,系统的load不到1,启动可以在秒级完成,并且已稳定运行近两个月。现在的架构,dns和mysql在同一物理机上,仅仅需要两台服务器,而这个数据量按原来的架构需要18台服务器,同时维护非常不便。
注:
1、dns一开始会有启动报错:
#service named start
Starting named: /opt/named/sbin/named: error while loading shared libraries: libmysqlclient.so.15: cannot open shared object file: No such file or directory
[FAILED]
解决办法:
a、编辑/etc/ld.so.conf 将mysql的lib目录加入
include ld.so.conf.d/*.conf
/usr/local/mysql/lib/mysql/
b、执行ldconfig 命令
2、dns是否关闭递归查询,对该结构的查询效率有一定影响。因为关闭递归会少执行n多sql语句。
[ 本帖最后由 ops 于 2008-12-12 19:48 编辑 ] |
|