Python套接字与线程池,如何提升性能?
我正在尝试实现一个基本的库,用来发送HTTP GET请求。我的目标是通过套接字连接来接收数据,设计尽量简单,以提高性能,并且能够与线程和线程池一起使用。
我有一堆链接,我根据它们的主机名进行分组,下面是一些输入网址的简单示例:
hostname1.com - 500 links
hostname2.org - 350 links
hostname3.co.uk - 100 links
...
我打算使用套接字是因为性能问题。我计划使用一些保持连接的套接字(如果可能的话,通常是可以的),并发送HTTP GET请求。这个想法源于urllib在连续请求时的低性能,后来我遇到了urllib3,发现它使用了httplib,然后我决定尝试使用套接字。所以到目前为止,我完成了以下内容:
GETSocket类、SocketPool类、ThreadPool和Worker类
GETSocket类是Python的httplib的一个简化版,只支持“HTTP GET”。
我这样使用这些类:
sp = Comm.SocketPool(host,size=self.poolsize, timeout=5)
for link in linklist:
pool.add_task(self.__get_url_by_sp, self.count, sp, link, results)
self.count += 1
pool.wait_completion()
pass
__get_url_by_sp
函数是一个包装器,它调用sp.urlopen
并将结果保存到results
列表中。我使用一个包含5个线程的池,并且有一个包含5个GETSocket类的套接字池。
我想知道,还有没有其他方法可以提高这个系统的性能?
我读过关于asyncore的内容在这里,但我不太明白如何使用class HTTPClient(asyncore.dispatcher)
来共享同一个套接字连接。
还有一点,我不知道我使用的是阻塞套接字还是非阻塞套接字,哪种对性能更好,或者如何实现其中一种。
请具体分享你的经验,我不打算导入其他库来仅仅做HTTP GET,所以我想自己编写一个小库。
任何帮助都非常感谢,谢谢。
2 个回答
这样做:
使用 multiprocessing
。可以查看这个链接了解更多信息:http://docs.python.org/library/multiprocessing.html。
写一个工作进程
Process
,把所有的URL放到一个Queue
(队列)里。写另一个工作进程
Process
,从Queue
中取出一个URL,进行GET请求,保存文件,并把文件信息放到另一个队列里。你可能需要多个这样的Process
。你需要尝试一下,找出合适的数量。再写一个工作进程
Process
,从Queue
中读取文件信息,执行你想要做的操作。
我终于找到了解决我问题的好办法。我在我的项目中使用Python 3,但我唯一的选择是用pycurl,这让我不得不把项目转回到Python 2.7版本。
使用pycurl,我得到了以下好处: - 对我的请求有一致的响应(实际上我的脚本需要处理至少1万个网址) - 通过使用ThreadPool类,我能以我系统能承受的最快速度收到响应(收到的数据会稍后处理,所以这里不太适合多进程处理)
我最开始尝试使用httplib2,但我发现它在Python 2上表现得更稳定,切换到pycurl后,我失去了缓存支持。
最终结论是:在进行HTTP通信时,可能需要像(p)curl这样的工具。这真是个救星,特别是当你需要处理大量网址时(有时候试试,真的会收到很多奇怪的响应)
谢谢大家的回复。