亚运赛事系统架构探索

广州亚运亚残在今天落幕了,一班亚运的同事将要离职,真让人伤感。随便写篇东西纪念一下我为亚运付出的一个月。

亚运赛事系统最初的系统架构,非常简单,就是前端用一堆组了lvs 的 squid 作为cache server ,后端跑nginx+resin 。

这个架构,优点就是够简单,如果cache server 不够,就横向扩展,同样简单。

但是,当整个系统的瓶颈不在缓存端时,缺点也很明显了。我发现,后端的load 很容易跑高,特点就是,缓存时间比较短(1 分钟),然后前端的穿透较多,再且,前端的访问很散列,并没有特别的热点。这样,如果作横向扩展,只会对后端的压力越大,因为穿透更多了。

之前去听SACC 2010 的,其实很多公司都用了一层haproxy 做 url hash 。于是,就对现有的架构作一次调整,希望对当时的负载情况有所帮助。

调整后的架构是这样的:最前端是一堆组了lvs 的haproxy ,作用是url hash 到后端的cache 。nginx 其实也是可以做url hash 的,在这里,选择nginx 还是 haproxy 呢,功能上nginx 确实稍胜一筹,但性能上 haproxy 也略优,选择什么也可以按个人爱好来定。呵呵。cache server 端,我也做了小调整,因为不需要只使用一个80 端口了,我一台服务器上跑两个squid 。用taskset 把2 个squid 绑定到cpu1 和 cpu2(默认都是cpu0 ) ,让cpu0 处理系统调用,cpu3 处理网络io 。一台4G 的服务器,在这个情况下已经算是把服务器使用得很尽了。cachedir 一律使用内存分区,不要出现磁盘io 。

但这个架构也不是绝对无敌,url hash 最怕遇到热点,特别热那种,就像110米跨栏决赛和男篮决赛。因为单一的url 并发过高,而导致其中一个cache server 跑满了一个cpu(url hash 把这个url 都调度到这个cache ) ,众所周知,squid 只能使用一个cpu ,这个cpu 跑满载了,请求就会开始阻塞了。然后连接数不断彪高,直接导致了前端的haproxy 也挂了,同时骨牌效应,所有的haproxy 都挂了。。。无奈,只好针对这个url 做特殊处理,rr 分配到后端多个squid ,而不走url hash 了。真是害人不浅阿。。。如果可以预先知道将会是热点的url ,这个问题将会更好解决,而不是要到haproxy 挂了才去处理。

末了,贴一下haproxy 的url hash 配置吧:

global
log 127.0.0.1 local3 notice
ulimit-n 409600
maxconn 102400
chroot /home/haproxy
pidfile /home/haproxy/var/haproxy.pid
user haproxy
group haproxy
nbproc 4
daemon
quiet

defaults
log global
mode http
option httplog
option dontlognull
option redispatch
option forwardfor
option httpclose
option log-separate-errors
monitor-uri /do_not_delete/monitor.txt
retries 3
stats uri /haproxy-status
maxconn 102400
contimeout 5000
clitimeout 50000
srvtimeout 50000
stats auth admin:123456

frontend http_server
bind :80
default_backend info_cache
acl url_static path_end BKM400101.json
use_backend info_cache_temp if url_static

backend info_cache
option httpchk HEAD /live.js HTTP/1.1\r\nHost:\ info.2010.163.com
balance uri len 15 # url hash
server inst1 192.168.51.1:3128 check inter 5000 fall 3
server inst2 192.168.51.1:3129 check inter 5000 fall 3
server inst3 192.168.51.2:3128 check inter 5000 fall 3
server inst4 192.168.51.2:3129 check inter 5000 fall 3
server inst5 192.168.51.3:3128 check inter 5000 fall 3
server inst6 192.168.51.3:3129 check inter 5000 fall 3

backend info_cache_temp
option httpchk HEAD /live.js HTTP/1.1\r\nHost:\ info.2010.163.com
balance roundrobin # rr
server inst1 192.168.51.1:3128 check inter 5000 fall 3
server inst2 192.168.51.1:3129 check inter 5000 fall 3
server inst3 192.168.51.2:3128 check inter 5000 fall 3
server inst4 192.168.51.2:3129 check inter 5000 fall 3
server inst5 192.168.51.3:3128 check inter 5000 fall 3
server inst6 192.168.51.3:3129 check inter 5000 fall 3

其实这个架构只是一个调优,如果整套系统需要优化的话,还是需要从最初的设计入手,很多细节都要顾及。

细节包括,那些数据传输的地址,不要使用163.com 的,因为带了很大串的cookie ,用户每一次访问都带有这么一大串,是很占带宽的。还有根据不同的文件设置不同的缓存,这个最初没有设计好的话,js , css 等文件就混入到163.com 的域名中难以隔离。还需要根据具体的业务去配置一下缓存。业务数据,一定要从一开始就要有系统地收集统计,调优后对比分析。等等等等。。。

在这个架构下,前面的haproxy 只是纯代理,后面的cache server ,可以任意选择,经典一点的,可以用 squid 。或者上varnish ,再或者试用 ATS 。

使用了nginx proxy_cache 引起的io 阻塞

这几天一直忙于解决各类莫名其妙的问题,今天遇到一个使用了nginx proxy_cache 的机器,io 出奇地高,简单处理了一下,简单记录下,没有太详细的数据。

这个nginx 的前面是一堆squid ,它作为一个二级缓存,这样对后端是很有好处的。

开发的同事说,这台机器使用了 proxy_cache 后,io 压力很大。

我粗略分析了一下,分析结果如下:

#vmstat 1

procs ———–memory———- —swap– —–io—- -system– —-cpu—-
r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
0  7     68  52720 437416 1325168    0    0     1     2    2    2  0  0 10  1
0  7     68  51916 437528 1325848    0    0     0  4000 2812 2737  0  2 6  90
0  7     68  51868 437624 1325644    0    0     8  3040 2808 2705  1  2 0  99
0  7     68  52540 437596 1325068    0    0     8     510 3040 2841  0  1 1  97
0  7     68  51668 437700 1325964    0    0    60     4033 3479 3220  1  2 5  90

可以看到procs 栏处于b 状态的很多,一般情况下是io 阻塞了

#ps aux

nobody   32622  1.1  0.6 530236 19248 ?        D    23:31   0:12 nginx: worker process

nobody   32623  0.9  0.6 530136 19064 ?        D    23:31   0:10 nginx: worker process

nobody   32624  0.9  0.6 530372 19276 ?        D    23:31   0:09 nginx: worker process

nobody   32625  1.1  0.6 530332 19296 ?        D    23:31   0:11 nginx: worker process

看下nginx worker 的状态,全是D,请求资源阻塞了?

#iostat -x 1

avg-cpu:  %user   %nice %system %iowait  %steal   %idle

0.00    0.00    0.00   16.16    0.00   83.84

Device:         rrqm/s   wrqm/s   r/s   w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util

sda               0.00     8.00  0.00 15.00     0.00   184.00    12.27     0.58   38.67   4.53   6.80

sdb               0.00   611.00  0.00 308.00     0.00  7200.00    23.38    98.31  193.23   2.27  70.00

粗略算一下,峰值io ,也就200r + 100w /s ,对于nginx 来说,这个应该算是中等,不算很高。但 %util 经常在 100.00 左右徘徊,这个就有点异常了。

看看配置吧,改改调调,发现引起问题的是以下这段配置

proxy_cache_path  /data/cache/proxy_cache_dir levels=2:2:2 keys_zone=cache_one:500m inactive=5d max_size=200g;

levels = 2:2:2

也就是nginx 那些缓存下来的文件,会存放到 $CACHE_PATH/[0-9a-f][0-9a-f]/[0-9a-f][0-9a-f]/[0-9a-f][0-9a-f]/xxxxxxxxxxxxxxxxxxxx 里

猜想,会不会是目录层次太多了呢?

改之,levels = 2:2

这里有个重点,改了nginx 配置还不能根治,还需要重建缓存目录。

改完,load 下来了,完成。

其实io 优化的最根本还是用内存分区,不会有io 阻塞。不过我没时间看他的架构,把问题解决了就算了,留个坑给后人吧。

cacti 又不能采集流量了

最近总遇到一些莫名其妙的问题,总要troubleshooting 。

先前cacti 出现过,到了一定流量时,就采集不到了。。。这个实在诡异,即使按照 joecen 说的,把output type id 改为64bit 都无济于事。。。

今天竟然发现cacti 完全不采集了!!在google 大神的帮助下,成功不明所以然地解决了,也记录一下吧。

直接原因是,采集的脚本出错:

执行,/usr/bin/php5-cgi /data/cacti/poller.php

Content-type: text/html
X-Powered-By: PHP/5.3.3

<br><strong>This script is only meant to run at the command line.</strong>

看来与cacti 本身没有关系,是php 执行错误。

祭出google 大神,修改 php.ini 的 register_argc_argv 为 on 。问题解决。

php 文档说,register_argc_argv 这个参数是

Tells PHP whether to declare the argv & argc variables (that would contain the GET information).

呃。。。我不懂 php ,我完全不知情!!^_^

grub 和 grub2 的重建

我的小黑是双系统,windows + ubuntu ,前者用来打游戏或者网上银行,基本很少用。但无奈,最近坏了,重装了个英文版的windows 上去,要重建grub 。grub 和 grub2 的重建会稍有不同,在这里 mark 一下。

开始的步骤都一致,我是用livecd ,也可以用usb 什么的,主要是要个linux 的环境。

grub 的重建:

sudo grub  # 进入grub ,之后的操作在 grub> 的提示符下进行

find /boot/grub/menu.lst # 没有错误的话,就会返回本来装载有grub 的分区,如 (hd0,1)

root (hd0,1) # root 刚才的返回

setup (hd0) # 安装grub

quit # 退出

sudo reboot 即可

###################################

grub2 的重建:

用grub 的方法已经不可行,不过要利用一下grub 的find 功能

sudo grub # 进入grub

find /boot/grub/grub.cfg # grub2 的菜单配置文件不再是 menu.lst ,而是grub.cfg ,没有错误的话,就会返回grub2 所在的分区 , 如 (hd0,1)

quit # 退出grub

(hd0,1) 也就是第一个硬盘的第二个分区,一般是 /dev/sda2

sudo mount /dev/sda2 /mnt # 挂载之前装有 grub 的分区

sudo grub-install –root-directory=/mnt /dev/sda  # 安装grub2

零编码实现非办公网络http 验证

有个需求,需要网站对非办公网络的访问进行验证,办公网络正常访问。
我山寨一下吧,没理由去改php 代码的。
不详说了,直接贴配置(别人贴代码我贴配置。。。)
set $safe 0 ;
location / {
if ($http_x_forwarded_for ~ (x.x.x.x)|(y.y.y.y)|(z.z.z.z) ){set $safe 1;}
if ( $cookie_bad_man = “x” ){ set $safe 1;}
if ($safe = 0){rewrite “^.*$” http://wp.helosa.org/redirect/ redirect;}
index index.html index.php;
root /data/wordpress/;
}
location /redirect/ {
charset utf-8 ;
alias /data/redirect/;
auth_basic “~oO-_-Oo~”;
auth_basic_user_file  htpasswd;
expires -1 ;
set $bad_man “x”;
add_header “Set-Cookie” “bad_man=$bad_man ; path=/; domain=wp.helosa.org”;
}
原理是,如果x-forwarded-for (因为前面有代理)符合办公网络ip ,放行(set $safe 1).
如果$safe 为0,跳转至 /redirect/ 目录
这个 /redirect/ 目录,设置http 验证,验证文件,用htpasswd 建一个吧
如果验证成功,set cookie ,主要是set 一个标示位,在这里是 bad_man ,当见到这个标志位的,也是放行的。
在 /redirect/ 下,有个index.html ,内容可以如下:
<html><body>
<meta http-equiv=”refresh” content=”0;url=http://wp.helosa.org/”>
</body></html>
主要用于跳转。
这样,就可以做到,办公网络不用验证,而在家访问,就要http 验证了。

我要发牢骚

好像10 月一篇文章都没有发过,好歹发一篇吧,结果就有了以下这篇牢骚。

看见别的部门,连翻墙的费用都可以报销,领导支持。这个我不介意,有些东西不是我可以改变的,但我改变不了并不代表我不能骂吧??你娘亲的(这句是骂那些把考勤当成考核成绩的领导,不是我的直接领导),我每晚工作到两三点,第二天要我准时上班??互联网公司不能弹性工作时间??

我是搞技术的, 不是写报告,写申请单,搞政治的,我不懂人情世故,我不懂勾心斗角,但我觉得,我在技术方面比你懂得多那么一点点,所以,在讨论技术话题时,请你shut up 。当然,如果你在我面前都shut up ,我没有意见。

其实有时候,我只是想静下来写两行代码。

ssh sftp 的设置

今天有个同事说他的 secure file transfer 使用不能。

看了下,貌似是 sshd_config 的配置有点问题,再看了下,原来是red hat 的配置用在了debian 上。

在 rh 系下,sshd_config 应该是

Subsystem       sftp    /usr/libexec/openssh/sftp-server

在 debian 下,应该是

Subsystem       sftp   /usr/lib/openssh/sftp-server

路径不一样了。。。

不良访问的封禁

最近有产品说有个搜索被调用得很厉害,已经影响了java 容器的性能了。去看了一下,似乎是有那么一回事,同一个ip 不断地搜同一个关键词。不过我想说。。。这些应该可以做缓存的阿,走缓存的话,刷一下就过去了,哪会影响性能。。。

用 fail2ban 封一下吧

debian 源里已经有 fail2ban 了,redhat 貌似还没有,下个源码安装吧,也挺快的。

wget “http://downloads.sourceforge.net/project/fail2ban/fail2ban-stable/fail2ban-0.8.4/fail2ban-0.8.4.tar.bz2?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Ffail2ban%2Ffiles%2F&ts=1285615174&use_mirror=cdnetworks-kr-2″

tar jxf fail2ban-0.8.4.tar.bz2

cd fail2ban-0.8.4

python setup.py install

cp files/redhat-initd /etc/init.d/fail2ban

chmod +x /etc/init.d/fail2ban

算是安装完毕了。

修改配置文件,/etc/fail2ban/fail2ban.conf 这个不用改,主要改这个 /etc/fail2ban/jail.conf

[DEFAULT]

ignoreip = 127.0.0.1  #这里最好加上办公区的ip ,呵呵,把自己封了就太傻B 了

bantime  = 600 #ban 它多久

findtime  = 600 #检查多长时间内的日志

maxretry = 3 #在监控的日志中,出现了多少次就要ban 了

backend = auto #好像是说读取日志文件的算法,这里让它自动吧

全局变量,下面可以覆盖的

有很多模块,定义一个自己的吧

[nginx-iptables]

enabled = true  # 启用模块的意思

filter = nginx  # filter.d/nginx.conf , 必须在这里面写点东西

action = iptables[name=NGINX, port=80, protocol=tcp]  # iptables 的设置

mail-whois[name=nginx, dest=you@admin.com]  # 报警设置,写自己的邮箱吧,要起sendmail 噢

logpath = /data/nginx/logs/t.access.log  # 监控的log

maxretry = 100 #10 分钟使用100 次,ban 了你!

添加 /etc/fail2ban/filter.d/nginx.conf

[Definition]

failregex = ^<HOST> -.*”(GET|POST) \/search\.json.* HTTP\/.*$  # 写自己的正则吧,符合这个正则的,就算一次fail ,10分钟内100 次(我的设置),就ban 了,<HOST> 可以指代ip 或 hostname 什么的

ignoreregex =

配置完成,启动服务:/etc/init.d/fail2ban start

启动后,mail-whois 这个action 会发一个邮件去你的邮箱,成功 ban 了ip 后,也会发过去,还可以定义 unban 也发的。这个邮件,还真的会帮你 whois 那个 ip 呢,很好很强大,呵呵

希望封了以后就世界安静了吧。。。

php 设置response header 时的小问题

今天遇到一个感觉很诡异的问题,就是 php 设置header 总是不成功,设置为返回xml ,但总是返回html 。源码大概如下:

<?php
echo “<?xml version=\”1.0\” encoding=\”UTF-8\”?>\n”;
header(“Content-Type: text/xml; charset=UTF-8″);
echo “<result>\n”;
echo “<success>false</success>\n”;
echo “</result>”;

?>

只要把header 一行移到第一个echo 的前面就行了

<?php
header(“Content-Type: text/xml; charset=UTF-8″);
echo “<?xml version=\”1.0\” encoding=\”UTF-8\”?>\n”;
echo “<result>\n”;
echo “<success>false</success>\n”;
echo “</result>”;

?>

对php 理解和实践都不深,猜测下,只要有了 echo 的话,php 就自动将返回头设定了,无论后面是否使用header() 函数,也无法改变它的 content-type 了。不知道php5.3 是否有改变,不知道是否还有更方便的方法设置 content-type ,不管了,我只是临时去解决了个小问题。

没文化真可怕阿,我的半桶水php 水平,差点就搞不掂今天的问题了。

再贴招聘启示

招聘招聘,给力点给力点!!

北京网易网站部招聘启示:

运维工程师-系统管理方向

工作职责:
  1、管理、维护网站部服务器及应用系统(如网易新闻,微博,跟贴等)
  2、研究、优化网站系统架构、提升系统服务性能

职位要求:
1、熟练使用Linux/unix操作系统,2年以上linux平台使用经验,大型网站管理经验者优先。
2、熟悉linux下Web服务软件,如apache squid resin nginx等。
3、熟练掌握perl、shell、python、ruby之一的脚本编程。
4、熟悉常见Web系统架构,并具有很强的故障排查和解决问题的能力。
5、工作认真细致、敬业,能承受较大的工作压力。
6、大学本科以上学历,计算机或相关专业。
------------------------------------ 华丽的分割线 ---------------------------------------
运维工程师-系统开发方向

工作职责:
  1、网站监控系统,运维管理系统的平台开发和优化
  2、高性能,高并发,高可靠web应用框架的研究与开发

职位要求:
1、熟练使用Linux/unix操作系统,2年以上linux平台使用经验。
2、熟悉计算机网络的基本知识及互联网上常见的通讯协议。
3、熟悉常见Web系统架构,了解大型网站的运维工作。
4、熟练Linux C编程,socket非阻塞编程,熟悉高性能web服务编程,有实际开发经验者优先。
5、工作认真细致、敬业,能承受较大的工作压力。
6、大学本科以上学历,计算机或相关专业。

有兴趣的同学,麻烦简历到 dc -e 2218434977265587644887655654201409471708622090P 这个地址。