2012-12-29 1 views
5

목표 : 우분투 12.04 PYTHON VER : 2.7 GEVENT VER 레디 스의 데이터 팝 (레디 스에서 팝 다음 큐에 넣어)gevent 블록 레디 스 '소켓 요청

RUNNING ENV와 몇 greenlet 작업자 거래를 생성 : 1.0 RC2 레디 스 VER : 2.6.5 레디 스-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) 

시도가 레디 스에서 데이터를 팝업 할 수 있지만,이 예외가 발생하지 blocked..and ... 단지 동결 및 제거 스폰 방법, 그것은 효과가있을 것입니다 .. 나는 pened, plz help! 태국!

답변

9

gevent는 cooperative 경량 프로세스 (스레드 아님)를 제공합니다. 결과는 어딘가에 무한 루프가 생겨 스케줄러가 다시 입력되지 않는 경우입니다. 프로그램은 CPU 코어의 100 %를 차지하는 것을 차단합니다.

예를 들어, 문제점은 사용자가 크롤러 루프를 정의한 방식입니다. 분명히 작업이 비어있을 때 무한 루프가 발생합니다. 그리고 gevent.sleep 호출 (필요한 yield 작업을 수행함)은 태스크가 비어 있지 않은 경우에만 호출되기 때문에 스케줄러가 다시 입력되지 않는다는 의미입니다.

연결이 Redis 클라이언트에 의해 지연되므로 lpop 명령에서 차단 된 것 같습니다. 이벤트 순서는 다음과 같습니다.

  • 작업 그룹이 스폰됩니다. 아직 미성년자는 예약되어 있지 않습니다.
  • redis_client가 구축되었지만 실제 연결이 지연되어 아직 I/O가 생성되지 않습니다.
  • lpop이 호출되었습니다. 이번에는 Redis 클라이언트가 연결 및 응답을 기다려야하기 때문에 연결이 실제로 필요합니다. 당신이 후 (루프 자체에 gevent.sleep()를 넣으면 작업 큐는 여전히

비어 있으므로 따라서, 스케줄러

  • 스케줄러가 크롤러 노동자에게
  • 무한 루프를 활성화로 산출 if), 더 잘 작동하지만, 여전히 dequeuer를 구현하는 것은 비효율적 인 방법입니다.

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

    경우 get() 호출이 노동자를 차단하므로 큐가 비어있는 동안은 노동자와 스케줄러의 탁구 게임을 피할 수 : 이런 식으로 뭔가 훨씬 더 좋을 것이다.

  • +0

    왜 이것을 다운 받습니까? – schlamar

    +0

    모르겠지만 여전히 내 대답에 서 있습니다 ;-) –