Tag: squid

当 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,暂时我也没办法。

 

亚运赛事系统架构探索

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

亚运赛事系统最初的系统架构,非常简单,就是前端用一堆组了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 。

当squid遇上502 bad gateway

测试环境:

192.168.1.1 (squid) , 192.168.1.2 (nginx proxy) , 192.168.1.3 (nginx web)

squid 作为最外层的代理;nginx proxy 作为第二层代理,通过upstream访问后台;nginx web 真正的数据后台web server。

测试开始:

$curl -I -H host:blog.lazybug.me http://192.168.1.1/test.html
 
HTTP/1.0 200 OK
Server: nginx/0.8.32
Date: Mon, 08 Feb 2010 18:11:48 GMT
Content-Type: text/html; charset=GBK
Expires: Mon, 08 Feb 2010 18:12:58 GMT
Cache-Control: max-age=70
X-Cache: MISS from proxy.lazybug.me
X-Cache-Lookup: HIT from proxy.lazybug.me:80
Via: 192.168.1.3.nginx, 1.1 proxy.lazybug.me:80 (squid/2.7.STABLE7)
Connection: close

此时, user -> squid -> nginx proxy -> nginx web

此时,这个页面已经被缓存住,往后的访问都是TCP_MEM_HIT的了。等到页面过期后,我把nginx web 后台弄挂,我在这里是直接把nginx proxy的upstream给改了,改为 192.168.1.4。此时,访问nginx proxy

$curl -I -H host:blog.lazybug.me http://192.168.1.2/test.html
 
HTTP/1.1 502 Bad Gateway
Server: nginx/0.8.32
Date: Mon, 08 Feb 2010 18:28:06 GMT
Content-Type: text/html
Content-Length: 173
Connection: keep-alive

因为根本没有192.168.1.4这个ip,肯定bad gateway了。

但此时访问squid

$curl -I -H host:blog.lazybug.me http://192.168.1.1/test.html
 
HTTP/1.0 200 OK
Server: nginx/0.8.32
Date: Mon, 08 Feb 2010 18:11:48 GMT
Content-Type: text/html; charset=GBK
Expires: Mon, 08 Feb 2010 18:12:58 GMT
Cache-Control: max-age=70
Age: 1004
Content-Length: 0
X-Cache: HIT from proxy.lazybug.me
X-Cache-Lookup: HIT from proxy.lazybug.me:80
Via: 192.168.51.3.nginx, 1.1 proxy.lazybug.me:80 (squid/2.7.STABLE7)
Connection: close

squid 仍然返回200,不过并不是立刻返回,而是经过了几秒才返回,因为此时squid认为请求页面过期,正在尝试去后端取新数据,但此时,后端返回一个502 bad gateway,那它的工作机制就是,返回旧的缓存数据给用户。

看一下squid的access.log,写着TCP_REFRESH_FAIL_HIT。查一下手册,如下:

An expired copy of the requested object was in the cache. Squid attempted to make an If-Modified-Since request, but it failed. The old (stale) object was delivered to the client.

如果 squid 没有缓存到页面,而出现502,squid 会不会返回200呢??测试下

清缓存:
squidclient -p 80 -m purge http://blog.lazybug.me/test.html

然后再次访问:

$curl -I -H host:blog.lazybug.me http://192.168.1.1/test.html
 
HTTP/1.0 502 Bad Gateway
Server: nginx/0.8.32
Date: Tue, 09 Feb 2010 18:17:13 GMT
Content-Type: text/html
Content-Length: 173
X-Cache: MISS from proxy.lazybug.me
X-Cache-Lookup: HIT from proxy.lazybug.me:80
Via: 1.1 proxy.lazybug.me:80 (squid/2.7.STABLE7)
Connection: close

呵呵,不出所料。

———————————————————————

结论:squid 作为前端代理,而后端502的话,如果squid已经缓存住的页面,那squid就返回用户旧的数据,如果squid没有缓存住的话,很遗憾,还是会502的。