五月, 2009


16
五 09

nginx的http session管理

http session,基本上可以认为就是我们平常所理解的完成GET或者POST请求的HTTP应用的TCP Session。

从自已的使用经验、以及归纳、总结网上各类关于Nginx的文章,个人觉得Nginx最擅长的是对静态内容提供HTTP服务,以及Session管理(HTTP任务管理)。Nginx使用了epoll的模式来管理TCP session,所以,性能高,系统资源消耗低。

实事上,Nginx提供动态内容需要通过FastCGI方式(也支持内置的对perl的支持),当觉得Nginx慢时,实际上是FastCGI慢(而FastCGI慢,大多数时候,又是因为数据库读写慢—-高并发的请求导致的阻塞属于不常见的原因之一,比如在遭遇DDos攻击的时候)。

大量的并发FastCGI请求,会使FastCGI管理器应接不暇(暂不去管后台数据库的因素,我们要解决的是FastCGI任务调度慢的情况),从而引起阻塞,引发系统上的“撞车效应”。所以瓶颈在FastCGI处理。

不少关于使用Nginx做负载均衡的例子,实际上就是利用Nginx的 session 管理能力。将处理较慢、花时间较多的FastCGI处理任务分发到多台系统上,这样可以提高系统的负载能力,提高系统发生阻塞的阈值。

Nginx的upstream模块,对“负载均衡”提供了良好的支持,详见:

http://wiki.nginx.org/NginxHttpUpstreamModule

例:
upstream app_group1 {
server 192.168.1.111:9000 weight=5 ;
server 192.168.1.112:9000 weight=5 ;
server 192.168.1.113:9000 weight=3 ;
server 192.168.1.114:9000 weight=5 ;
}

…………

location ~ \.php$ {
fastcgi_pass   app_group_01;
fastcgi_index  index.php;
fastcgi_param  SCRIPT_FILENAME  $fastcgi_script_name;
include        extra/fastcgi_params.conf;
}

之前,是将Nginx分别放在四台FastCGI服务器上,然后使用LVS来作负载调度,运行良好。为了给系统构架分层,使架构清晰,更易于管理和扩展,降低维护难度,试着使用Nginx来调度负载。

一个较明显的效果是四个FastCGI的系统负载下降(原来有Nginx运行在同一系统上)。

Nginx系统的负载很低,活动连接1.7k左右,负载系统不超过1,用掉不到50M的物理内存。相对于LVS复杂的实施以及背后的管理成本,Nginx在低于100M流量的应用中相当有优势。


15
五 09

给cacti添加对nginx的统计

官方论坛上有详细说明

http://forums.cacti.net/about26458.html

需要说明的是,本地系统可能没有安装perl的LWP模块,对于CentOS系统来说:

yum -y install perl-libwww-perl

即可。

另一个,便是编译nginx时增加 –with-http_stub_status_module 选项

然后,在Server容器里增加如下配置:

location /status {
stub_status             on;
access_log              off;
allow   192.168.0.0/16;
deny    all;
}


12
五 09

tar之新发现

之前见到tar解压之后的文件或目录的uid和gid为数字,于是错误地以为(这之间似乎也没什么逻辑),tar打包时只记录了uid和gid的数字信息。

然而事实并非如此。

当本地系统上有相同的user时,那么tar解压时,会自动将uid和gid转换成本地相同用户名和组名的uid和gid。

于是这般,方便多了。也合情合理。


11
五 09

Apache关闭ETag头儿

在主配置文件段里添加了

FileETag None

但实际上并不总是有效,原因还没有找到。于是使用下面的方式:

<IfModule mod_headers.c>
header unset Etag
</IfModule>

可行。


7
五 09

处理ddos攻击经验小结

昨天,系统在较短的时间内,某一台机器上有9千多ip,对同一域名,同一文件,以相同的agent,没有referer,进行了七百多万次的访问。于是,先是前端的负载彪升,然后机房的限制下行若干M带宽被用尽,于是攻击效果几何级增长,全线瘫痪,所有服务器都连不上了。

1. 假如不是带宽耗尽,我们能负载得了么?

发现两个问题。
第一,是 ip_conntrack 的问题,net.ipv4.netfilter.ip_conntrack_max 默认 65536 ,就是说,系统只能处理65536个连接,大于这个值时,就会阻塞,收到 kernel: ip_conntrack: table full, dropping packet.这样的信息。并且,系统负载上升。这个玩意儿本来是供给NAT使用的,到现在为止,还没有找到启动iptables,但不加载ip_conntrack模块的办法。为了增加系统处理能力,需要增加这个值,我在rc.local里增加了 sysctl -w net.ipv4.netfilter.ip_conntrack_max=655360 。但是发现无效:原因是,当iptables启动之后,该参数才有效。并且,重启iptables后,该参数会被初始化成默认值。当系统负载高的时候,就出引发 ip_conntrack: table full, dropping packet 导致的连接阻塞问题。
但是我怀疑一件事情,一味的增大此值,是否是在解决问题的根本。六万多连接,定是因为连接处理不了,阻塞而积累起来的。一味的放宽限制,不是意味着连接阻塞问题将导致更多资源被耗尽?

猜想:前端是用了nginx的,就是说高并发,对于nginx并不能够成威胁,那么大量的连接阻塞,定然是出在了fast-cgi处理上。高并发的请求,一下子涌向fast-cgi,于是……

故且不管这些,在高负载的系统上,还是先停止iptables这样的应用吧。尽管是内核级的应用,不占用什么资源。

第二,关于打开文件数的限制。
又是经验性的致命错误。在/etc/security/limits.conf里,增加了对daemon用户打开文件数的限制。然而似乎并没有起到作用。后来突然明白,daemon只是运行程序的用户,是root启动程序后,set的euid,应该是没有以该uid被始化环境,而是直接继承的root用户的环境。所以,这个设置也是没有生效的!

准备采用另外的方法,将ulimit -n 10240 这样的语句写进apache和nginx的启动脚本里,这样,系统就清洁了。并且走到哪里都不会有问题。

2. 抱着主动的态度,ddos的时候,能做些什么?

确定攻击类型之后,有几件事儿可以做。
第一,换IP地址。
第二,查攻击IP,封IP。
第三,查攻击目标,处理之(似之占用负载最小)。

不同的攻击类型,有不同的处理方法。但基本上,ddos最终是要将系统资源耗尽。

第二和第三可同时进行。但是这两个,只有当是小流量的攻击的时候,才可能有机会和时间这么做。需要说明的是,在遭受攻击之情形下,使用iptables封IP时,应使用reject,而不应该使用drop。根据实验结果,reject可以有效降低对方发包的速度,从而降低对带宽的影响。

将受攻击的目标通过DNS解析走,或者封掉,或者禁止访问,可有效降低对系统负载的消耗,但无异是一种对“网络暴力”的妥协,委屈求全。

换IP是个不错的方法,只要对方不是玩命的跟你死磕,一般都能凌效。一般的ddos攻击不会持续时间很长,一来,调动大量的肉鸡,是在消耗自己的资源,攻击的时间越大,将损失的肉鸡就会越多,二来,自己的淫威已经得到证明,没有必要死磕下去。但是换IP地址对用户的影响比较大。从换解析到全部生效,需要一段时间。不是万不得已,还是不用为好。
需要注意的是,原IP必须停止使用,不能配置在任何一台自己的主机上。

假如有抗DDOS攻击的设备,那就另当别论了,或者能在电信部门的配合,能在路由器上做些处理,那效果就更明显了。


4
五 09

我的若干参数

T恤(刚好) :胸围 108  衣长 67/69  肩宽 44  袖长 67

衬衫(略小):胸围 102  衣长 74    肩宽 48  袖长 64

风衣(刚好):胸围 108  衣长 88    肩宽 47  袖长 66

衬衫(稍大):胸围 112  衣长 76           肩宽 48


3
五 09

将Apache的日志发送到syslog服务器

一直想要统一收集管理Apache的日志,一来可以较实时的分析系统的负载情况、分析系统问题,另一个,也可以把收集日志的工作分散到平时,分散带宽使用,并且解决日志合并问题。

想到的解决方法主要有两个:

第一,使用haproxy。

haproxy本身刚好就支持将日志以udp的方式发送给syslog服务器。看上去完美、感觉上官方。

第二,使用/bin/logger。

这个,是我晚上发梦的时候想到的。试图将CustomLog 管道给/bin/logger,再由本地的syslog forward到远程统一的syslog服务器上。实验了一下,居然成功了。就是绕了那么一道弯子,感觉不太完美。

PS:

发布之后,自己搜了一下,发现了下文:http://www.lslnet.com/linux/dosc1/32/linux-247167.htm

解决方法倒也差不多,不过多了些详细的描述,很实用。

并且要注意:至少默认的syslog配置会将短时候内重复的日志记录给于提示,并不记录:

May  3 14:31:51 localhost last message repeated 99 times

另外,将nginx的日志发送到syslog:

mkfifo  /srv/logs/access_log.fifo

将 nginx 的日志写到这个 管道文件上

然后:logger -f /srv/logs/access_log.fifo 即可。