最近的项目开发中,Gearman中的worker使用Python中的urllib/urllib2库大量抓取网页时,总会出现某个Worker阻塞,偶尔一旦发生worker都被阻塞,就会造成任务大量丢失,为检查原因所在,为什么任务出现中断,就写个脚本,利用strace命令,查看所有woker的快照,发现最终被阻塞在recv函数中,然后程序源代码,发现与网络读取有关的,也就是urllib/urllib2中的相关函数,幸亏项目就是监控远程的WEb应用是否活跃,在大量抓取中,已经遭遇很多服务器故意欺骗,因而当时就觉得是服务器故意不传用数据,致使worker阻塞,但是阻塞的时间又太长,按理说python中的socket 都应该设置有超时时间,不至于一直不放,为了验证想法,当时就写个简单的服务端程序,接收到数据后,故意不返回任何数据:
HOST = '172.23.16.42' PORT = 1024 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(1) conn, addr = s.accept() print 'Connected by', addr while 1: data = conn.recv(1024) if data: print data while 1: continue conn.sendall(data) conn.close() |
实际运行后,整体结果如下:
发现持续快一小时,依旧被阻塞,因而需要自己实际设置超时,改用urllib2库,有超时的设置,然后在运行实际程序,发现一旦超时,客户端自动返回
因而在实际的编程中,特别是有关网络的操作,需要查明默认的超时情况,并根据自己的需要实际设置自己的超时时间,不然会遭遇意想不到的事情。