gpt4 book ai didi

python - gevent 阻止 redis 的套接字请求

转载 作者:IT王子 更新时间:2023-10-29 05:57:46 26 4
gpt4 key购买 nike

GOAL:spawn a few greenlet worker 处理从redis弹出的数据(从redis弹出然后放入队列)

运行环境:ubuntu 12.04 python 版本:2.7GEVENT 版本:1.0 RC2版本:2.6.5REDIS-PY VER:2.7.1

from gevent import monkey; monkey.patch_all()
import gevent
from gevent.pool import Group
from gevent.queue import JoinableQueue
import redis

tasks = JoinableQueue()
task_group = Group()

def crawler():
while True:
if not tasks.empty():
print tasks.get()
gevent.sleep()

task_group.spawn(crawler)
redis_client = redis.Redis()
data = redis_client.lpop('test') #<----------Block here
tasks.put(data)

尝试从 Redis 中弹出数据,但它被阻止了......并且没有引发异常......只是卡住并删除 spawn 方法,它将起作用..我对发生的事情感到困惑,请帮忙!谢谢你!

最佳答案

gevent 提供协作 轻量级进程(不是线程)。结果是当你在某个地方有一个无限循环并且永远不会重新进入调度程序时,程序将阻止占用 100% 的 CPU 内核。

在您的示例中,问题在于您定义爬虫循环的方式。显然,当 tasks 为空时,您将进入无限循环。并且因为 gevent.sleep 调用(将执行必要的 yield 操作)仅在任务不为空时调用,这意味着永远不会重新进入调度程序。

它似乎阻塞在 lpop 命令上,因为连接被 Redis 客户端延迟了。事件的顺序如下:

  • 任务组成立;但还没有安排 greenlet
  • redis_client 已构建,但由于实际连接已延迟,因此尚未生成 I/O
  • lpop 被调用;这次确实需要连接,因为 Redis 客户端必须等待连接和对 lpop 的回复;因此它屈服于调度器
  • 调度器激活一个爬虫 worker
  • 无限循环,因为任务队列仍然是空的

如果你将 gevent.sleep() 放在循环本身中(在 if 之后),它会工作得更好,但它仍然是实现出列器的低效方法。这样的事情会好得多:

def crawler():
while True:
x = tasks.get()
try:
print "Crawler: ",x
finally:
tasks.task_done()

get() 调用阻塞了 worker,因此它将避免在队列为空时 worker 和调度程序之间的乒乓游戏。

关于python - gevent 阻止 redis 的套接字请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14078493/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com