December 2010

cnnic 证书更新问题

最近为部门内部系统的https 快要过期的证书更新,出现了一系列的问题,很是郁闷!!一个字:恨!!

原来从2010 年 3 月后,由cnnic 签发的证书,有所改变了。2010 年 3 月前,root CA 是 entrust ,中级CA 是cnnic 。3 月后,root 和中级CA ,都是cnnic 了。。。

cnnic 证书本身就没有多少诚信可言了,还做了root CA 。。。

举例说明:

$curl -I https://blog.helosa.org/ 的时候,会有这类报错

curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a “bundle”
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn’t adequate, you can specify an alternate file
using the –cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you’d like to turn off curl’s verification of the certificate, use
the -k (or –insecure) option.

提示是说,加一个-k 的参数,就不会去验证证书了,但我想了解一下原因。它也给了提示,让我们去这个网页http://curl.haxx.se/docs/sslcerts.html 里了解详情。

通读了一次,大概了解了,因为root 和中级CA 都是cnnic ,并且根CA 的证书并不在curl 的信任列表里,curl 认为它是self-signed 证书,不安全,于是就报错了。

解决方案嘛,把cnnic 的root 证书wget 回来,在这里:http://www.cnnic.cn/uploadfiles/cer/2010/3/2/113823.cer

然后curl 时加上这个证书,curl –cacert 113823.cer https://blog.helosa.org/

=====================================================

在这个问题上,我有两个不明白的地方:

1,其实,可以将cnnic 的root 证书加入到信任列表的,信任列表在/etc/ssl/certs/ 里,通过 curl -vv 可以看到

CAfile: none

CApath: /etc/ssl/certs

/etc/ssl/certs/ 里的文件,其实都是软链,软链到firefox 的证书目录吧,这个 /usr/share/ca-certificates/mozilla/ 。

既然如此,那我把cnnic root 的证书扔进去,总可以了吧?结果发现,还是不行的,难道是名字也有要求?格式不对?

2,朋友用mba 的curl 帮我测试,是正常的,是因为cnnic 的root 证书在信任列表吗?日后入手了mbp 再测试!

亚运赛事系统架构探索

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

亚运赛事系统最初的系统架构,非常简单,就是前端用一堆组了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 ,我完全不知情!!^_^