eventletでgearman worker
eventletっていうライブラリが僕好みの匂いを発していたので遊んでいる。 gearmanを使って、ブログのURLを与えたらそこのFeedのリストを返すってWorkerを書いていたので、それをeventlet化してみよう。
まず、gearmanのeventlet化、gearmanのライブラリにはpure-pythonのやつを使っていたのでさくっと行けた。
green_gearman.py
from eventlet import patcher
from eventlet.green import socket, select
for mod in ['worker', 'connection']:
patcher.inject('gearman.%s' % mod, globals(),
('socket', socket),
('select', select)
)
del patcher
eventletにはpatcherというざっくりしたモジュールがあって、これを使うと指定したモジュールのglobalsを置き換えてくれる。これでいいんかなっていうぐらい簡単。
試しにecho serverを書いてみる。
from eventlet import coros, api
from green_gearman import GearmanWorker
def echo_func(job):
print api.getcurrent(), job.arg
time.sleep(5.)
def main():
pool = coros.CoroutinePool(max_size=200)
waiters = []
for idx in range(10):
worker = GearmanWorker(['0.0.0.0:4730'])
worker.register_function('echo', echo_func)
waiters.append(pool.execute(worker.work))
for w in waiters:
w.wait()
main()
gearmanのprotocolは同時に1ジョブしか処理できないっぽいので、とりあえず10個ぐらい突っ込んでみる。
gearman -h localhost -p 4730 -s -f echo hogehogeを20個ぐらい飛ばしてみた所、
<greenlet.greenlet object at 0x804137f30> hogehoge
<greenlet.greenlet object at 0x804127c90> hogehoge
<greenlet.greenlet object at 0x804137db0> hogehoge
<greenlet.greenlet object at 0x804137e10> hogehoge
ってなってるので、なんかまぁそれっぽくなってる気がする。こんなコードじゃよくわからんな… これで良いのでしょうか。
さて肝心のWorkerもこれにのせたいのだが、urllib2を使っていたので、代わりにfrom eventlet.green import urllib2に代えるだけっぽい(まだやってない…)。
んでつらつらコード見てたんだが、今のところ(eventlet 0.9.2)はlibeventサポートがdisabledされているようで、ちょっとがっかり。
eventlet化する場合、全てのIOをこれにしないとブロックが発生してみんな止まることになっちゃうのだけど、MySQL周りとかをeventlet化するのはめんどくさそうなのでアレでアレしてアレですね。