【发布时间】:2014-09-28 14:13:23
【问题描述】:
我正在创建一个 HTTP 客户端,它每秒可以生成数百个连接,并在每个连接上发送多达 10 个请求。我正在使用线程,因此可以实现并发。 这是我的代码:
def generate_req(reqSession):
requestCounter = 0
while requestCounter < requestRate:
try:
response1 = reqSession.get('http://20.20.1.2/tempurl.html')
if response1.status_code == 200:
client_notify('r')
except(exceptions.ConnectionError, exceptions.HTTPError, exceptions.Timeout) as Err:
client_notify('F')
break
requestCounter += 1
def main():
for q in range(connectionPerSec):
s1 = requests.session()
t1 = threading.Thread(target=generate_req, args=(s1,))
t1.start()
问题:
-
在 requestRate = 1 的情况下,它无法扩展到超过 200 个连接/秒。我在同一台客户端计算机上运行其他可用的 HTTP 客户端并针对服务器,测试运行良好并且能够扩展。
当 requestRate = 10 时,连接数/秒降至 30。 原因:无法每秒创建目标数量的线程。
对于问题 #2,客户端计算机无法创建足够的请求会话并启动新线程。一旦 requestRate 设置为大于 1,事情就开始分崩离析。 我怀疑它与请求使用的 HTTP 连接池有关。
请提出我在这里做错了什么。
【问题讨论】:
-
为什么要重用同一个
session对象?据我了解,您的connectionPerSec实际上是指并行线程数,requestRate实际上是每个线程上的串行请求数。您可能还想查看concurrent.futures。 -
会话对象仅在衍生线程中重用,因此它对所有串行请求使用相同的连接。
-
似乎来自 concurrent.futures 的 ThreadPoolExecutor 与我正在尝试做的事情相同?
-
请注意,在 CPython 中,线程的并发性是有限的:一次只有一个线程可以执行 Python 字节码。全局解释器锁强制执行此限制以简化内存管理。
标签: python multithreading python-requests