2012-12-29 30 views
5

MỤC TIÊU: đẻ trứng một vài thỏa thuận lao động greenlet với pop dữ liệu từ redis (pop từ redis và sau đó đưa vào hàng đợi)gevent yêu cầu ổ cắm khối redis'

CHẠY 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) 

Cố gắng pop dữ liệu từ redis, nhưng nó blocked..and không phải ngoại lệ huy động ... chỉ cần đóng băng và loại bỏ phương pháp đẻ trứng, nó sẽ làm việc .. tôi cảm thấy bối rối những gì hap pened, plz giúp đỡ! thk u!

Trả lời

9

gevent cung cấp hợp tác xã quy trình nhẹ (không phải chủ đề). Kết quả là khi bạn có một vòng lặp vô hạn ở đâu đó và bộ lập lịch không bao giờ được nhập lại, chương trình sẽ chặn lấy 100% lõi CPU.

Trong ví dụ của bạn, vấn đề là cách bạn đã xác định vòng lặp trình thu thập thông tin. Rõ ràng, bạn có một vòng lặp vô hạn khi nhiệm vụ trống. Và bởi vì cuộc gọi gevent.sleep (có thể thực hiện thao tác năng suất cần thiết) chỉ được gọi khi các tác vụ không trống, điều đó có nghĩa là trình lên lịch không bao giờ được nhập lại.

Dường như chặn lệnh lpop do kết nối bị trễ bởi trình khách Redis. Chuỗi sự kiện như sau:

  • nhóm tác vụ được sinh ra; nhưng chưa có greenlet được lập lịch nào
  • redis_client được tạo nhưng chưa tạo ra I/O vì kết nối thực sự bị trễ
  • lpop được gọi; thời gian này kết nối thực sự cần thiết vì khách hàng Redis phải đợi kết nối và trả lời cho lpop; do đó nó mang lại để trình lên lịch
  • scheduler kích hoạt một nhân viên thu thập thông
  • vòng lặp vô hạn, vì nhiệm vụ hàng đợi vẫn còn trống

Nếu bạn đặt gevent.sleep() trong vòng lặp chính nó (sau khi nếu), nó sẽ hoạt động tốt hơn, nhưng nó vẫn là một cách không hiệu quả để thực hiện một dequeuer. Một cái gì đó như thế này sẽ tốt hơn nhiều:

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

Cuộc gọi get() chặn nhân viên, vì vậy nó sẽ tránh trò chơi ping pong giữa nhân viên và người lên lịch trong khi hàng đợi trống.

+0

Tại sao điều này lại được giảm giá? – schlamar

+0

Tôi không biết nhưng tôi vẫn đứng bởi câu trả lời của tôi ;-) –