我写了一个带有套接字的pythonic服务器。 它应该同时(并行(接收请求并并行响应它们。 当我向它发送多个请求时,应答时间比我预期的要多。
服务器:
import datetime
import asyncio, timeit
import json, traceback
from asyncio import get_event_loop
requestslist = []
loop = asyncio.get_event_loop()
async def handleData(reader, writer):
message = ''
clientip = ''
data = bytearray()
print("Async HandleData", datetime.datetime.utcnow())
try:
start = timeit.default_timer()
data = await reader.readuntil(separator=b'rnrn')
msg = data.decode(encoding='utf-8')
len_csharp_message = int(msg[msg.find('content-length:') + 15:msg.find(';dmnid'):])
data = await reader.read(len_csharp_message)
message = data.decode(encoding='utf-8')
clientip = reader._transport._extra['peername'][0]
clientport = reader._transport._extra['peername'][1]
print('nData Received from:', clientip, ':', clientport)
if (clientip, message) in requestslist:
reader._transport._sock.close()
else:
requestslist.append((clientip, message))
# adapter_result = parallel_members(message_dict, service, dmnid)
adapter_result = '''[{"name": {"data": "data", "type": "str"}}]'''
body = json.dumps(adapter_result, ensure_ascii=False)
print(body)
contentlen = len(bytes(str(body), 'utf-8'))
header = bytes('Content-Length:{}'.format(contentlen), 'utf-8')
result = header + bytes('rnrn{', 'utf-8') + body + bytes('}', 'utf-8')
stop = timeit.default_timer()
print('total_time:', stop - start)
writer.write(result)
writer.close()
writer.close()
# del writer
except Exception as ex:
writer.close()
print(traceback.format_exc())
finally:
try:
requestslist.remove((clientip, message))
except:
pass
def main(*args):
print("ready")
loop = get_event_loop()
coro = asyncio.start_server(handleData, 'localhost', 4040, loop=loop, limit=204800000)
srv = loop.run_until_complete(coro)
loop.run_forever()
if __name__ == '__main__':
main()
当我发送单个请求时,它也需要 0.016 秒。 但对于更多的要求,这次增加。
CPU 信息 :英特尔至强 X5650
客户:
import multiprocessing, subprocess
import time
from joblib import Parallel, delayed
def worker(file):
subprocess.Popen(file, shell=False)
def call_parallel (index):
print('begin ' , index)
p = multiprocessing.Process(target=worker(index))
p.start()
print('end ' , index)
path = r'python "/test-Client.py"' # ## client address
files = [path, path, path, path, path, path, path, path, path, path, path, path]
Parallel(n_jobs=-1, backend="threading")(delayed(call_parallel)(i) for index,i in enumerate(files))
对于同步发送 12 个请求的客户端,每个请求的总时间为 0.15 秒。
我希望对于任何数量的请求,时间都是固定的。
什么是请求
单个请求(粗略地说(包括以下步骤:
- 将数据写入网络
- 浪费时间等待答案
- 从网络读取答案
您的 CPU 处理的 No1/No3 非常快。步骤No2 - 是从您的PC到某个服务器(例如在另一个城市(并通过电线返回的字节旅程:通常需要更多时间。
异步请求的工作原理
异步请求在处理方面并不是真正的"并行":它仍然是您的单个 CPU 内核,一次可以处理一件事。但是运行多个异步请求允许您使用某个请求的步骤 No2 来执行其他请求的步骤 No1/No3,而不仅仅是浪费大量时间。这就是为什么多个异步请求通常会比相同数量的同步请求更早完成的原因。
运行异步代码,无网络延迟
但是当你在本地运行东西时,步骤No2不需要太多时间:你的PC和服务器是一回事,字节不会进入网络旅程。只是没有时间可以在步骤 No2 中使用来启动新请求。只有您的单个 CPU 内核一次处理一件事。
您应该针对延迟应答的服务器测试请求,以查看预期的结果。