2012-12-29 14 views
5

GOAL:Ubuntuの12.04 PYTHON VER:2.7 GEVENT VERのRedisからのデータのポップ(Redisのからポップし、キューに入れ)geventブロックRedisのソケット要求

RUNNING ENVで数greenlet労働者の契約を生みます:1.0 RC2 RedisのVER:2.6.5 のRedis-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のからデータをポップしてみたが、それが上がっも例外をblocked..andない...ただ を凍結し、削除スポーンメソッド、それは働くだろう.. pened、plzヘルプ! thk u!

答えて

9

gevent cooperative軽量プロセス(スレッドではありません)を提供します。その結果、どこかで無限のループが発生し、スケジューラが再入されない場合、プログラムはCPUコアの100%をブロックします。

例では、問題はクローラループを定義した方法です。明らかに、タスクが空のときは無限ループになります。タスクが空でない場合にのみgevent.sleep呼び出し(必要なyield操作を実行する)が呼び出されるのは、スケジューラーが再入力されないことを意味します。

Redisクライアントによって接続が遅延しているため、lpopコマンドでブロックされているようです。イベントシーケンスは次のとおりです。

  • タスクグループが生成されました。未処理の予定はありません
  • redis_clientが構築されていますが、実際の接続が遅延しているため、I/Oはまだ生成されません。
  • lpopが呼び出されました。今回は接続が本当に必要です。なぜなら、Redisクライアントは接続と応答をlpopに待たなければならないからです。それゆえ後(ループ自体に)(あなたはgevent.sleepを入れた場合は、タスクキューがまだ

空であるため、スケジューラは、クローラワーカー

  • 無限ループを活性化し、スケジューラ
  • にもたらしif)、それはうまくいくが、それでもdequeuerを実装するのは非効率的な方法である。このような何かがはるかに良いでしょう:キューが空である間、それは労働者とスケジューラの間でピンポンゲームを避けることができますので、

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

    のget()の呼び出しは、労働者をブロックしています。

  • +0

    なぜこれがダウン表示されますか? – schlamar

    +0

    私は知らないが、私はまだ私の答えで立っている;-) –

    関連する問題