2012-12-29 16 views
5

CEL: zapoczątkować kilka Greenlet wiele roboczy z podręcznego danych z REDiS (POP z REDiS, a następnie wprowadzone do kolejki)gevent żądanie gniazdo REDIS BLOCK

RUCH ENV ubuntu 12,04 PYTHON VER: 2,7 GEVENT VER : 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) 

Spróbuj pop dane z REDiS, ale blocked..and żaden wyjątek podniesiony ... po prostu zamrozić i usunąć metoda odrodzenia, zadziała .. czuję się zagubiony, co się stało pened, plz help! thk u!

Odpowiedz

9

gevent zapewnia kooperatywne lekkie procesy (nie wątki). Konsekwencją jest sytuacja, gdy masz gdzieś nieskończoną pętlę, a program planujący nigdy nie zostanie przywrócony, program zablokuje pobieranie 100% rdzenia procesora.

W twoim przykładzie problemem jest sposób, w jaki zdefiniowałeś pętlę robota. Oczywiście masz nieskończoną pętlę, gdy zadania są puste. A ponieważ wywołanie gevent.sleep (które wykonałoby niezbędną operację wydajności) jest wywoływane tylko wtedy, gdy zadania nie są puste, oznacza to, że program planujący nigdy nie jest ponownie wprowadzany.

Wydaje się blokować na komendzie lpop, ponieważ połączenie jest opóźnione przez klienta Redis. Kolejność zdarzeń jest następująca:

  • grupa zadań jest spawnowana; ale nie zaplanowano jeszcze zieloności:
  • jest zbudowany obiekt redis_client, ale nie generuje jeszcze operacji wejścia/wyjścia, ponieważ faktyczne połączenie jest opóźnione:
  • Nazywa się lpop; tym razem połączenie jest naprawdę potrzebne, ponieważ klient Redis musi poczekać na połączenie i odpowiedź do lpop; dlatego też daje do terminarza
  • planista aktywuje pracownikowi gąsienicowe
  • nieskończoną pętlę, gdyż kolejka zadań jest jeszcze pusty

Jeśli umieścisz gevent.sleep() w samej pętli (po jeśli), będzie działał lepiej, ale nadal jest nieefektywnym sposobem na zainstalowanie dezinstalatora. Coś takiego byłoby znacznie lepiej:

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

get() wezwanie blokuje pracownika, więc będzie uniknąć gry ping pong między pracownikiem a scheduler, gdy kolejka jest pusta.

+0

Dlaczego są odrzucane? – schlamar

+0

Nie wiem, ale wciąż jestem przy mojej odpowiedzi ;-) –