我正在尝试实现一个基本的库来发出HTTP GET请求。我的目标是通过套接字连接接收数据 -极简设计以提高性能 -使用线程,线程池。
我有一堆链接,我按它们的主机名分组,所以这里有一个简单的输入url演示:
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,所以我想编码我自己的小库。
任何帮助,感谢。
这样做。
使用multiprocessing
。http://docs.python.org/library/multiprocessing.html。
-
写一个worker
Process
,把所有的URL放到Queue
. -
写一个worker
Process
,它从Queue
获取URL并执行GET,保存文件并将文件信息放入另一个队列。您可能需要此Process
的多个副本。你必须尝试找出多少是正确的数字。 -
写一个worker
Process
,它从Queue
读取文件信息,并做任何你想做的事情。
我终于找到了解决问题的良方。我在我的项目中使用Python 3,我唯一的选择是使用pycurl,所以这使我不得不将我的项目移植回Python 2.7系列。
使用pycurl,我得到了:-一致的响应我的请求(实际上我的脚本必须处理最少10k的url)-使用ThreadPool类,我的系统可以尽可能快地接收响应(接收到的数据稍后处理-因此多处理在这里不太可能)我先尝试了httplib2,我意识到它不像在Python 2上那样稳定,通过切换到pycurl,我失去了缓存支持。
最后的结论:当涉及到HTTP通信时,可能需要一个像(py)curl这样的工具。这是一个救星,特别是当一个人在处理大量的url时(有时尝试好玩:你会得到很多奇怪的回应)
谢谢大家的回复。