一种巨型网站的 DNS 服务器流量优化方案

中国的门户网站,只 NS 服务器就能产生不少网络流量呢;而且因为随时可能会更改域名指向,以切换服务器组,域名的 TTL 还不能太大,甚至有低于 RFC 规定的300秒的情况。

其实这类服务还是有很大的优化余地的。我们来比划一下 DNS 的解析过程:

  1. 访客的电脑向 ISP 的 DNS 提出解析请求
  2. ISP 的 DNS 向 root、gTLD/ccTLD 服务器提出请求,得到网站的域的 NS 地址及其 A记录
  3. ISP 的 DNS 向该域的 NS 服务器提出查询,得到最终结果,返回给访客

这里面其实只有第一步是必须的,无法优化的,而后面的粗流量完全可以缩小成涓涓细流。解决方法就是让各主流 ISP 的 DNS 作为知名网站的域的 hidden slave NS,直接从主 NS 服务器获得权威数据,向辖区的访客提供解析服务。这样,多次重复递归解析的巨大流量变成了 AXFR/IXFR 的小流量,主 NS 服务器的压力和网络流量也会大大减小。而 ISP 的 DNS 反正都是要为访客提供解析服务的,改变角色之后并没有增加任何压力,反而减少了流量指出,提高了响应速度。

技术上不是问题,问题是门户网站和 ISP 的态度,不知道双方是否有足够的诚意去合作。

Posted in 默认分类 | Tagged , | 5 Comments

电信通污染专线客户的 DNS 请求,真是太无耻了

今天上新浪微博,发现页面乱了,明显是 css 下载失败的现象。开 firebug 看到,下载 css 的步骤被 301 到北京网通的导航页面去了。顺手 dig 了一下那个文件所在的域名 timg.sjs.sinajs.cn,发现那个 IP 竟然和我公司的 IP 很接近,是电信通的!!直接访问那个 IP ,是 squid 的错误页面,页面尾部也没署名。这个现象和网通的 NXDOMAIN Redirect 的现象是不同的。

不过,为什么连电信通的缓存服务器都自动 301 到北京网通的导航页面去了呢?看起来他们也在用北京网通DNS,且北京网通 DNS 也无法解析新浪的域名。

继而发现,在自己的电脑上,不论向哪个 DNS  服务器查询,出来都是那个结果,且 TTL 不会降低,保持在300,还有个现象就是应答里没有AUTHORITY和ADDITION SECTION。这说明电信通在线路上做了 DNS 拦截,直接转到他们自己的 DNS 服务器去了。ssh 登录外面托管的服务器上,解析那个域名,给出的是一系列 CNAME 最后一个 A,那个 A 看着就顺眼,北京电报局的网段。

 

下午又看了一个视频,发现浏览器状态栏提示从 124.207.162.83 下载数据。这个 IP 地址和刚才解析新浪微博的那个假 IP 124.207.162.88 是同一个网段的。经过一番折腾(具体过程参见前一篇博客),终于发现 img.uu1001.cn 也被污染了。

我们奉劝这些小 ISP,没本事就别揽这么多专线接入生意,不要拿垃圾缓存服务器来糊弄客户,以为我们都是外行吗?

11月18日补记:经过昨天一天的投诉,今天终于取消了上述两个域名的污染。不过 img.kaixin001.com.cn 还有各门户网站的静态文件域名依然被污染。

Posted in 默认分类 | Tagged , | 4 Comments

其实SYSOP手段也不是万能的,今天被迫动了一下dnsmasq的源码

今天发现电信通拦截DNS请求,把热门流量导向其内部 squid 缓存服务器。今天主要发现有两个,一个是新浪微博的 css 文件所在的域名 timg.sjs.sinajs.cn 被指向了 124.207.162.88 ,另一个是……查看某个视频的时候,浏览器状态栏提示从 124.207.162.83 下载数据,跟新浪微博被拦截的域名指向同一个 IP 段。但是页面里并没有写是从哪个域名下载视频的。于是乎,我想从公司网关的 dnsmasq 上取得数据,却意外的发现 –log-queries 参数无效,开启该参数后,按文档说明发 USR1 信号给 dnsmasq ,syslog 里却没看到 cache dump。

找了一台 Debian 看了看,是可以的。于是我立即习惯性的阴暗的认为是 RedHat 的软件质量问题。找了一套原装正品源码,编译后发现行为也是一样的。无奈了,SYSOP 手段也不是万能的,只好开始看源码。

源码里搜索 log-queries 找到 getopt 这个步骤,找到其内部名字 OPT_LOG。然后在源码文件里找这个,发现了 cache.c 文件里的 cache_dump 函数中,关于 dump cache 功能的逻辑,这一句是这么写的:

if ((daemon->options & (OPT_DEBUG | OPT_LOG)))

回头找一下 OPT_DEBUG,发现是 –no-daemon 参数。也就是说,只有这俩参数同时用,才能 dump cache,这样不符合 manpage 的描述。于是把 OPT_DEBUG 去掉。编译再试,发现还是不行。又

在 src/cache.c 文件的 cache_dump 函数中,发现几句 my_syslog 函数的 log facilty 有问题,改掉,就 OK 了。btw:加语句调试的过程中,觉得这个 my_syslog 长得很像 fprintf。

重新回去放视频,dump cache,终于在日志里看到了这么一句:
[root@dl360g5 log]# tail -f messages|grep 124.207
Nov 16 17:02:39 dl360g5 dnsmasq[24252]: img.uu1001.cn                            124.207.162.83                 4F        Tue Nov 16 17:07:37 2010

已经报了bug。经与作者讨论,发现自己原文中关于 if 语句判断条件的内容是错误的,故修正。真正原因是 dnsmasq 把 cache dump 输出到了 LOG_DEBUG,而 CentOS 的 syslog 默认不记录 *.debug

124.207.162.88
Posted in 默认分类 | Tagged , , , , | 3 Comments

有人忘记在 ifcfg 里写 NETMASK 了,结果……

我的好兄弟、大学同学谢某人,在虚拟机里玩 RHEL+Oracle 的时候,遇到一个诡异的事情,就是 RHEL 开机后 IP 地址会自动变化。我原以为是他装 Oracle 的时候某个开机自动执行的命令更改了地址,所以就在开机的各 rc 脚本之间夹带执行一次 ifconfig 命令,发现在开机过程中 IP 地址始终都是没有变化的。持续 ping 该机器,发现在出现登录提示符后才 ping 不通,并且提示符后还出现了 iscsi-initiator 关于断开和 target 的网络连接的错误提示信息。

没办法,看日志吧。/var/log/messages 日志明明白白的写着:NetworkManger 认为长度为零的 IP prefix 是无效的,因此接管了该网卡,并按 Auto eth0 设置了该网卡。看了看 ifcfg 文件,里面果然是没写掩码。此时谢同学不服气的嚷嚷,说另一个虚拟机也是这么写的,就不会自动变 IP。过去看了一下,发现那边没启动 NetworkManager 服务。哈哈……

不过有个问题,ifconfig 命令对于不带掩码的 IP 地址,会自动按照 A/B/C 类别给予掩码,为什么 NetworkManager 不看网卡上已经设置上的掩码,而去看 ifcfg 呢?这果然是个奇怪的东西。另外:建议对 Linux 不熟悉的,使用 GUI/TUI 界面的工具设置参数。比如 RedHat 的 setup 命令就不错。

Posted in 默认分类 | Tagged , , , , | Leave a comment

用 SYSOP 风格的方法研究 spawn-fcgi

不怕大家笑话,以前我一直不明白为啥会有 spawn-fcgi 这个东西。因为以前都是用 PHP 啊,PHP 本身就是可以并发处理多个请求的 fastcgi server 啊,要 spawn-fcgi 干啥用呢?更有意思的是有人用 spawn-fcgi 启动多个 php-cgi ,然后这个 php-cgi 再启动多个子进程,不知道有什么好处。

前几天,我读了一下代码,还是没太明白这个东西存在的必要性,于是就用我们 SYSOP 的方法研究了一下 spawn-fcgi:

fakefcgi.sh脚本文件
#!/bin/sh
ls -l /proc/self/fd/ >/var/log/$$.txt
sleep 600s

执行
spawn-fcgi -p 3333 -F 5 -- ./fakefcgi.sh
得到结果
spawn-fcgi: child spawned successfully: PID: 16868
spawn-fcgi: child spawned successfully: PID: 16871
spawn-fcgi: child spawned successfully: PID: 16872
spawn-fcgi: child spawned successfully: PID: 16873
spawn-fcgi: child spawned successfully: PID: 16874

执行pstree发现spawn-fcgi没在运行,各个fakefcgi.sh都直接隶属于init。看来是个daemonizer。

再看日志文件:
# cat *.txt
总用量 0
lrwx------ 1 root root 64 10月 22 14:07 0 -> socket:[281459]
l-wx------ 1 root root 64 10月 22 14:07 1 -> /var/log/16868.txt
lrwx------ 1 root root 64 10月 22 14:07 2 -> /dev/null
lr-x------ 1 root root 64 10月 22 14:07 3 -> /proc/16869/fd
总用量 0
lrwx------ 1 root root 64 10月 22 14:07 0 -> socket:[281459]
l-wx------ 1 root root 64 10月 22 14:07 1 -> /var/log/16871.txt
lrwx------ 1 root root 64 10月 22 14:07 2 -> /dev/null
lr-x------ 1 root root 64 10月 22 14:07 3 -> /proc/16875/fd
总用量 0
lrwx------ 1 root root 64 10月 22 14:07 0 -> socket:[281459]
l-wx------ 1 root root 64 10月 22 14:07 1 -> /var/log/16872.txt
lrwx------ 1 root root 64 10月 22 14:07 2 -> /dev/null
lr-x------ 1 root root 64 10月 22 14:07 3 -> /proc/16877/fd
总用量 0
lrwx------ 1 root root 64 10月 22 14:07 0 -> socket:[281459]
l-wx------ 1 root root 64 10月 22 14:07 1 -> /var/log/16873.txt
lrwx------ 1 root root 64 10月 22 14:07 2 -> /dev/null
lr-x------ 1 root root 64 10月 22 14:07 3 -> /proc/16876/fd
总用量 0
lrwx------ 1 root root 64 10月 22 14:07 0 -> socket:[281459]
l-wx------ 1 root root 64 10月 22 14:07 1 -> /var/log/16874.txt
lrwx------ 1 root root 64 10月 22 14:07 2 -> /dev/null
lr-x------ 1 root root 64 10月 22 14:07 3 -> /proc/16878/fd

执行
# netstat -ane|grep 281459
其中 281459 是前面的 socket 号码。得到的结果是:
tcp        0      0 0.0.0.0:3333            0.0.0.0:*               LISTEN    0          281459
现在明白了,原来spawn-fcgi只是让多个单循环的 fastcgi server 监听在同一socket上而已。直接调用 libfcgi 库,主程序里只有一个 fastcgi 处理循环,这样开发出来的 fastcgi server 就需要 spawn-fcgi 配合,要不然就无法处理并发的请求。

Posted in 默认分类 | Tagged , , | 1 Comment

nginx 的 if 语法好严格呀!

今天被机房通知删网站内容,我发转给相应的同事了。然后我自己就在 nginx 里折腾看能不能先把那个网址改成 403。试了半天,发现 nginx.conf 里用 if 指令判断 querystring 里的内容的时候,等号前后都得有空格,像这样:
if ( $arg_uid = 877363 ) { return 403;}
如果没有空格就不行,看着像是 nginx 不知道那个变量名和操作符号有多长,需要用空格来分隔的意思。

Posted in 默认分类 | Tagged | Leave a comment

在小饭馆看到的 HTTP 502 错误实例

周五拉着 wincss  去蓟门里的螺蛳粉先生吃饭,期间见到了一个场景,颇像当年 5D6D 网站遭遇的 502 错误。

我和 wincss 到饭馆的时候,屋里已经没有座位了。但是既然来了也不能轻易放弃啊,于是要求店家在外面支了桌子。其实瓶颈主要在于厨房(数据库),厨房做饭太慢,外面的客户只好先排着。在客人数量(请求数量)没有超出饭馆桌椅数量( fastcgi server 的进程和 backlog 上限)的情况下,系统 load 迅速增大,但还没崩溃,此时所有的吃饭请求都挂着,处于 I/O blocked 状态。

过了一会,饭还没做好。有些人等不及就撤了,于是发生了 HTTP 504 Gateway Timeout 错误。而不断前来的客人开始怨声载道(因为他们站在饭店门口的路上,所以载道),此时就发生了 HTTP 502 Bad Gateway 错误。

502、504 错误的根本原因在于系统搭配不均衡,后端的单点瓶颈和前端负载能力过于强大的搭配是不合适的。唯一值得庆幸的是,即使厨房很慢,我们索要辣椒调料的请求还是得到了满足,类似于 fastcgi 请求无法满足的时候,静态文件请求仍能满足的情况。

Posted in 默认分类 | Tagged , | 3 Comments

买了个相机

自从上次妈妈来京参加合唱比赛,让我负责摄影,第一次接触了单反和变焦镜头,就迷上了影像凝固的乐趣和快门的声音。

经过两个星期的背景知识学习、品牌认知、商业情报调查,今天终于在位于五棵松北的北京摄影器材城买了一台 Nikon D90 套机,花费 7100 元。另购有 8G 容量 Class4 速度的 SD 卡和用于保护镜头的所谓 UV 镜(当然,大家都知道这个价格的 UV 镜是防不了紫外线的)

出了器材城,在公交车站看到一位漂亮小 mm,但是我脸皮太薄,没好意思拍之,实在是可惜,可惜!

晚上到家,换上 bugs 给的 90周年纪念版背带,感觉确实比原装的好一些。

本次采购,鸣谢bugs、Jackos、谢珮英同学等。

Posted in 默认分类 | Tagged , , , | Leave a comment

高温步行

没注意,昨天竟然是最高温的一天,恰恰在这天,我突发奇想要去看广场降旗。

下班后,顺着建国路、建国门内大街、长安街疾行了54分钟,到广场。GPS记录显示:平均10分28秒就能走一公里。广场上,两个便衣士兵陪军装士兵聊天,要不然我觉得那个军装士兵可能也会像游客一样晕倒。降旗之后我觉得自己的脚底板都发烫。刚刚降旗完毕,就清场了,广播、警察和武警把游客送出了广场。我从地下通道出广场的时候突然感觉有点眩晕,可能是天太热了,出汗太多了。想买瓶水,却发现附近只有游商。唉,还是不放心啊。无奈,接着走吧。走到电报大楼对面,终于有了一条小街道,拐进去果然有商店,旁边还有个厕所呢!长安街还是太政治了,连摆摊都不让,真是的!喝了水,感觉好多了。不过因为出汗太多,那个厕所我也没用得上。

接着走,到新文化街视察了一下《功夫梦》的拍摄地鲁迅中学。不过当时已经很晚了,用手机拍照几乎无法成像。步行走回西单,地铁回家去也。

今天中午在 Google Earth 量了一下,昨天步行的里程约8.5km。

Posted in 默认分类 | Tagged , , , | 1 Comment

RHEL6 作为 xen domU 虚拟机,启用 hvc0 的方法

今天在 xen  虚拟机里安装了 RHEL6 beta,发现因为 sysvinit 被换成 upstart 之后,竟然不知道在哪里启用 hvc0 上的 getty 了。尝试改变 /etc/sysconfig/init 把 hvc0加到 ACTIVE_CONSOLES 里,但是开机时提示 hvc0 permission denied 之类的提示信息。

最后还是在内核上加 console= 参数了。不过注意:必须写成 console=tty console=hvc0 这样,其中 tty 那一项可以用 console=tty 也可以用 console=tty1。

  • 如果只加console=hvc0 则用VNC查看虚拟机的时候看不到开机时的 dmesg 和服务脚本启动信息
  • 如果顺序反了,最后不会启动 agetty 在 hvc0 上,该行为在 /etc/init/serial.conf 提到了

RHEL6 在启动脚本中自动检测内核参数中最后一个 console 参数是否为串口,如果是串口就在上面运行一个 agetty 。不知道其它使用 upstart 代替 sysvinit 的发行版是否也有类似行为。

Posted in 默认分类 | Tagged , , , | 4 Comments