Tag: troubleshooting

puppet 在 mongodb 的机器上卡死

好久没写技术的内容了, 要长草了… 随便写一篇今天的吧 ( 同事发现的…我只是搬运工 )

现象: 在部分跑着 mongodb 的机器上跑 puppet , 巨卡, 竟然需要跑好几十分钟, 并且 top 看起来还是 system 占用的 cpu 资源而不是 user .

解决:

因为众所周知的原因, 跑 mongodb 时必须关闭 NUMA 来启动. 看了以下这个页面, 才发现还需要关闭 zone_reclaim_mode. 因为此值默认总是关闭的, 所以一直没有为意.

http://docs.mongodb.org/manual/administration/production-notes/#production-numa

因为某些原因, 我们上周开启了 /proc/sys/vm/zone_reclaim_mode, 导致的问题.

http://www.kernel.org/doc/Documentation/sysctl/vm.txt , 已经提醒过大家, 最好关闭了.

http://www.poempelfox.de/blog/2010/03/, 解释最全了. 阐述了多种症状, 我们都命中了…例如一个普通的系统调用需时甚长.

唉, 关闭了 zone_reclaim_mode 就好了.

当 QQ 的离线图片遇上正向代理的 Squid

blog 荒废了好久。。。都长草了。自从去了陌陌以后,就没有写过一篇 blog 了,但期间其实做了不少东西的,可惜不是那么容易拿出来分享。

对很多东西有了很多新的认识,例如不再那么厌恶 CentOS 。终于尝试了一回 nginx_lua ,还用它写了一个传图系统,代替那个恶心的 NFS 。全面开始自动化管理,真的不需要经常 ssh 上去的。为大家带来更多我认为高效的工具。

好了,回到题目,说说情况吧。首先,办公室是一定需要翻墙的,只需要放一个兼容 PC 作为办公室的网关,就解决了,同时,还搭建一个 squid ,主要为了缓存一些 itunes 更新吧,哗哗的!!次要,可以缓存一些陌陌的图片啦(大家都有习惯刷一些周围的mm的图片),缓存一下微博的图片啊(如果大家关注的人都一样的话)

把内网往 80 的访问都重定向到 squid (在 192.168.18.1 的 3128 ):

iptables -t nat -A PREROUTING -s 192.168.18.0/24 -i eth0 -p tcp -m tcp –dport 80 -j DNAT –to-destination 192.168.18.1:3128
iptables -t nat -A POSTROUTING -j MASQUERADE

一切运行正常的,但同事总是说 QQ 发图片收不到什么的,一直没在意,今天实在想修一下了!!

由于我以前一直不用 Q ,还真不知道还真的会出现这种事情。。。

如果是发送 QQ 离线图片的话,会把图片分块上传到几台服务器(124.89.102.x , 124.115.10.x ),由于我把所有对外的 80 的包都导向到 squid 了,发送离线图片的时候,在squid 的日志中看到,不断地 POST 到那个 ip,抓包看到一堆的 “tcp segment of a reassembled PDU” ,感觉是经过 SQUID 以后,分段的 POST 无法在 QQ 那边合并起来了。

其实呢。。。说了这么多,其实我是还没找到真正的方法去解决的。。。但我又没空搭理这个小问题,还有很多线上的业务要忙呢,只好绕过了。

iptables -t nat -A PREROUTING -d 124.89.102.0/24 -i eth0 -p tcp -m tcp –dport 80 -j ACCEPT
iptables -t nat -A PREROUTING -d 124.115.10.0/24 -i eth0 -p tcp -m tcp –dport 80 -j ACCEPT

mark 一下,当QQ离线图片遇上正向代理的 Squid,暂时我也没办法。

 

nginx+apache+dav_svn 的怪异问题

最近帮朋友的网站做个小优化,由apache 迁移到nginx ,结果问题多多,svn 在提交的时候竟然有这个错误:

$ svn ci -m”fix the mail problem “
Sending        util.php
svn: Commit failed (details follow):
svn: File ‘util.php’ is out of date
svn: ‘/svn/!svn/bc/496/trunk/util.php’ path not found
但是提交其它文件貌似没有问题。怪异到爆!!!

首先说说nginx 的配置。

svn 仍然使用 apache 的dav_svn ,只是端口由80 改为 1234,其它配置不改。

location  /svn {

proxy_pass http://127.0.0.1:1234 ;

proxy_set_header Host “svn.mysite.net” ;

}

终于在google 大神找到一篇俄文的mailing-list(http://www.lexa.ru/nginx-ru/msg39625.html),竟然有人和我同样的错误,也终于弄清楚什么事了。。。简直是自己白痴!!
我的php 的配置:
location ~ \.php$ {
root           /var/www/backend/  ;
fastcgi_pass   127.0.0.1:9000;
fastcgi_index  index.php;
include        fastcgi.conf;
}
这个location 用了正则匹配,比svn 的普通location 优先级高,结果svn 提交util.php 的时候(会发送一堆svn 的指令如propfind , option 等),优先到php 的location 里,结果就出错了。。。
那svn 也用高优先级的location 匹配吧,修改一下,用前缀匹配:
location ^~ /svn
ok , 成功了。。。
事后我才看到,nginx 本身就有一个404 的log :
211.102.143.12 – hello [03/Jul/2011:15:34:53 +0800] “PROPFIND /svn/!svn/bc/496/trunk/util.php HTTP/1.1″ 404 31 “-” “SVN/1.6.15 (r1038135) neon/0.28.6″ “-“
唉。。。怪自己~~

kernel 2.6.32 的服务器作为lvs 的rs 无法建立tcp 连接的问题

最近用xen 的虚拟机作为lvs 的rs 组了一下lvs ,发现上线以后,无法与client 建立tcp 连接,开始还以为是xen 的bridge 网络的问题,后来才把问题定位到系统内核。其实之前也出现过类似的问题的,但当时急着上线,没去研究了,这回太忙,连测试环境都搭出来了,也都没空去深究,今天同事帮我测试了一下,倒是完全明白了。

问题描述:

LVS 用dr 的方式组起来以后,访问vip 时,无法与real server 建立tcp 连接。tcpdump 看到只有client 过来的syn 包,rs 并不返回ack 包,根本无法完成tcp 握手。用curl 来模拟访问测试的话,会看到这样的返回 curl: (7) couldn’t connect to host 。

看看我的配置吧。

lvs director :

采用dr 的调度方式,通过内网把请求分配到real server

lvs 的 real server :

内核为 2.6.32-5-amd64 (2.6.32 这个内核很普遍了,debian 6 和 rhel 6 默认都这个了),不响应arp 配置

echo “1” >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo “2” >/proc/sys/net/ipv4/conf/lo/arp_announce
echo “1” >/proc/sys/net/ipv4/conf/all/arp_ignore
echo “2” >/proc/sys/net/ipv4/conf/all/arp_announce

其它基本的配置就不说了,如果就这样子起服务后,就会出现我描述的问题了。

原因在于内核的这个参数 : reverse path filtering,这个是啥,我摘抄一下:

Reverse Path Filtering (RPF) is a technology that is used on InternetProtocol routers to try and prevent source address spoofing, which is often used for DenialOfService attacks. RPF works by checking the source IP of each packet received on an interface against the routing table. If the best route for the source IP address does not use the same interface that the packet was received on the packet is dropped. There are some situations where this feature will obviously not be the desired behaviour and will need to be disabled. In general if you are not multi-homed then enabling RPF on your router will not be a problem.

简单地说,就是如果从eth1 接收到包,就不会从eth0 返回,内核把这个包丢弃。

正好我们的LVS 就是这样的服务模式,lvs director 接收到client 对vip 的访问,经过包的重写通过内网把包分配给rs ,rs 直接使用外网返回这个client 的请求。正好就会被rp_filter 给干掉了。

但是,为什么我们以前并没有出现过类似的问题呢??看看rp_filter 的默认内核配置

net.ipv4.conf.eth1.rp_filter = 1

net.ipv4.conf.eth0.rp_filter = 1

net.ipv4.conf.lo.rp_filter = 0

net.ipv4.conf.default.rp_filter = 1

net.ipv4.conf.all.rp_filter = 0

rp_filter 的值的意义是:

814 rp_filter – INTEGER

815 0 – No source validation.

816 1 – Strict mode as defined in RFC3704 Strict Reverse Path

817 Each incoming packet is tested against the FIB and if the interface

818 is not the best reverse path the packet check will fail.

819 By default failed packets are discarded.

820 2 – Loose mode as defined in RFC3704 Loose Reverse Path

821 Each incoming packet’s source address is also tested against the FIB

822 and if the source address is not reachable via any interface

823 the packet check will fail.

0 就是对进来的包完全不作检查,这样有被dos 攻击的风险。

1 就是严格检查,只要不是这个interface 的包,就不返回。

2 就是不太严格,只要本机配置了这个ip ,还是可以返回的。

对于lvs 来说,用2 也是可以的。

只要把eth1 的 rp_filter 的值置为 0 ,lvs 的服务就能正常了。

从这里可以找到答案:http://www.spinics.net/lists/linux-net/msg17162.html

The first patch changed rp_filter from a boolean to an integer, and the

second patch changed the way the interface-specific value and the “all”

value are combined to produce a functional value from a logical AND to

an arithmetic MAX.

Before patches : functional value = interface AND all

After patches  : functional value = MAX(interface, all)

So now if net.ipv4.conf.all.rp_filter=1, source validation is enabled on

all interfaces as their functional value is at least 1. You may either

set net.ipv4.conf.all.rp_filter to 0 (to disable it) or 2 (to enable

loose mode globally), or set net.ipv4.conf.$interface.rp_filter to 2 (to

enable loose mode on $interface).

I guess that the patch suggested by Dave Miller is related to another

(apparently incomplete) change that occured in 2.6.32 :

在2.6.31 , 对于rp_filter 的最终值,有了不同的计算方法。

之前,是只要设置了all.rp_filter 为0 ,那么就是0 了。

之后,看具体的interface 和 all 的值的最大值来取最终值。

默认是 net.ipv4.conf.eth1.rp_filter = 1 和 net.ipv4.conf.all.rp_filter = 0 ,因此,组lvs 的时候,就会丢弃包了。

问题解决!!下次调一下内核参数吧。

PS:可以通过设置这个内核参数来查看一下log

echo 1 >/proc/sys/net/ipv4/conf/<interfacename>/log_martians

64 位linux 上安装svn 1.4.x 的错误

很久没更新了,随便更新一篇吧,2011 年的1 月一篇blog 都没有post 。。。皆因全去做杂事了。做事情的人了,没有技术上的长进阿!

部门内部的svn 用了很旧的版本,1.4.6 了,最近把它迁移到一台64 bit 的机器上,svn 编译不过去,具体报错如下:

cd subversion/libsvn_ra_dav && /bin/sh /home/download/subversion-1.4.6/libtool –tag=CC –silent –mode=link gcc  -g -O2  -g -O2 -pthread    -rpath /usr/local/lib -o libsvn_ra_dav-1.la  commit.lo fetch.lo file_revs.lo log.lo merge.lo options.lo props.lo replay.lo session.lo util.lo ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la /home/download/subversion-1.4.6/apr-util/libaprutil-0.la -lexpat /home/download/subversion-1.4.6/apr/libapr-0.la -lrt -lm -lcrypt -lnsl  -lpthread -ldl /home/download/subversion-1.4.6/neon/src/libneon.la -lz
/usr/bin/ld: /home/download/subversion-1.4.6/neon/src/.libs/libneon.a(ne_request.o): relocation R_X86_64_32 against `a local symbol’ can not be used when making a shared object; recompile with -fPIC
/home/download/subversion-1.4.6/neon/src/.libs/libneon.a: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [subversion/libsvn_ra_dav/libsvn_ra_dav-1.la] Error 1

其实它也提到了解决方案,recompile with -fPIC ,但。。。我不知道在哪里加……

祭出google 大神,竟然要自己手动改Makefile 。。。

修改 neon/src/Makefie 的 CFLAGS 为 -fPIC -g -O2

困扰了一会,顺便更新一下blog 。

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 再测试!

使用了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

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

路径不一样了。。。