Python Asyncio 如何 itertools.cycle 同时处理超过 1 个请求
Python Asyncio How To itertools.cycle with more than 1 Request At The Same Time
我正在使用 Sanic,我们正在使用代理来建立外部连接以进行网络抓取。
我想创建一个 python 字典,并在 python 字典中放置一个代理列表。在此字典中,我们将存储 0
、1
等值。 1
= 代理连接失败。
我希望均匀地访问一个列表,因此我们的代理在一段时间内的使用方式有一些可预测的模式。而不是随机选择它们可能会大量使用 1 个代理而不是其他代理。
但是,由于Sanic有很多工人。我正在想办法解决这个问题。
在视觉上我的想法是,它就像一排代理,每次请求时,上面的代理执行下一步,一旦被调用,它就会再次到线的后面。
类似 https://docs.python.org/2/library/itertools.html#itertools.cycle 似乎是个不错的选择。
但是,我的问题是......这怎么会发生异步和非阻塞。作为工作者或请求可以同时发生。如果同时发生 2-50 个请求,如何解决这个问题。
您最好的选择可能是查看类似 aredis 的内容。 Worker 本质上是子流程,因此共享字典不起作用。
如果您查看使用 worker 设置的源代码,请在名为 serve_multiple
的方法中进一步查看
def serve_multiple(server_settings, workers):
"""Start multiple server processes simultaneously. Stop on interrupt
and terminate signals, and drain connections when complete.
:param server_settings: kw arguments to be passed to the serve function
:param workers: number of workers to launch
:param stop_event: if provided, is used as a stop signal
:return:
"""
server_settings['reuse_port'] = True
# Handling when custom socket is not provided.
if server_settings.get('sock') is None:
sock = socket()
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
sock.bind((server_settings['host'], server_settings['port']))
sock.set_inheritable(True)
server_settings['sock'] = sock
server_settings['host'] = None
server_settings['port'] = None
def sig_handler(signal, frame):
logger.info("Received signal %s. Shutting down.", Signals(signal).name)
for process in processes:
os.kill(process.pid, SIGINT)
signal_func(SIGINT, lambda s, f: sig_handler(s, f))
signal_func(SIGTERM, lambda s, f: sig_handler(s, f))
processes = []
for _ in range(workers):
process = Process(target=serve, kwargs=server_settings)
process.daemon = True
process.start()
processes.append(process)
for process in processes:
process.join()
# the above processes will block this until they're stopped
for process in processes:
process.terminate()
server_settings.get('sock').close()
Redis 有一个队列,因此您可以从队列中取出一些东西,然后在需要时替换它。
我想你可以用 nginx 实现代理?
我正在使用 Sanic,我们正在使用代理来建立外部连接以进行网络抓取。
我想创建一个 python 字典,并在 python 字典中放置一个代理列表。在此字典中,我们将存储 0
、1
等值。 1
= 代理连接失败。
我希望均匀地访问一个列表,因此我们的代理在一段时间内的使用方式有一些可预测的模式。而不是随机选择它们可能会大量使用 1 个代理而不是其他代理。
但是,由于Sanic有很多工人。我正在想办法解决这个问题。
在视觉上我的想法是,它就像一排代理,每次请求时,上面的代理执行下一步,一旦被调用,它就会再次到线的后面。
类似 https://docs.python.org/2/library/itertools.html#itertools.cycle 似乎是个不错的选择。
但是,我的问题是......这怎么会发生异步和非阻塞。作为工作者或请求可以同时发生。如果同时发生 2-50 个请求,如何解决这个问题。
您最好的选择可能是查看类似 aredis 的内容。 Worker 本质上是子流程,因此共享字典不起作用。
如果您查看使用 worker 设置的源代码,请在名为 serve_multiple
的方法中进一步查看 def serve_multiple(server_settings, workers):
"""Start multiple server processes simultaneously. Stop on interrupt
and terminate signals, and drain connections when complete.
:param server_settings: kw arguments to be passed to the serve function
:param workers: number of workers to launch
:param stop_event: if provided, is used as a stop signal
:return:
"""
server_settings['reuse_port'] = True
# Handling when custom socket is not provided.
if server_settings.get('sock') is None:
sock = socket()
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
sock.bind((server_settings['host'], server_settings['port']))
sock.set_inheritable(True)
server_settings['sock'] = sock
server_settings['host'] = None
server_settings['port'] = None
def sig_handler(signal, frame):
logger.info("Received signal %s. Shutting down.", Signals(signal).name)
for process in processes:
os.kill(process.pid, SIGINT)
signal_func(SIGINT, lambda s, f: sig_handler(s, f))
signal_func(SIGTERM, lambda s, f: sig_handler(s, f))
processes = []
for _ in range(workers):
process = Process(target=serve, kwargs=server_settings)
process.daemon = True
process.start()
processes.append(process)
for process in processes:
process.join()
# the above processes will block this until they're stopped
for process in processes:
process.terminate()
server_settings.get('sock').close()
Redis 有一个队列,因此您可以从队列中取出一些东西,然后在需要时替换它。
我想你可以用 nginx 实现代理?