J'ai essayé sans succès d'utiliser TXredis (l'API torsadée non bloquante pour ReDIS) pour une file d'attente de message persistante, j'essaie de créer un projet Scrapy que je travaille. J'ai constaté que bien que le client ne bloquait pas, il a été devenu beaucoup plus lent qu'il aurait pu être dû au fait que ce qui aurait dû être un événement dans la boucle de réacteur a été divisé en milliers d'étapes.
Afin, j'ai essayé de faire usage de Redis -py (l'API torsadée de blocage régulière) et enveloppant l'appel dans un fil différé. Cela fonctionne très bien, mais je souhaite effectuer un appellé à l'intérieur lorsque je voudrais faire un appel à Redis, car je voudrais configurer la mise en commun de la connexion dans les tentatives pour accélérer plus loin. p>
ci-dessous est mon interprétation de certains échantillons de code prélevé dans les documents tordus pour un fil différé pour illustrer mon étui d'utilisation: p> et voici ma modification Pour la mise en commun de la connexion qui rend le code dans le blocage de fil différé: P> #!/usr/bin/env python
from twisted.internet import reactor,defer
from twisted.internet.task import LoopingCall
import time
def main_loop():
print 'doing stuff in main loop.. do not block me!'
def aBlockingRedisCall(x):
if x<5: #all connections are busy, try later
print '%s is less than 5, get a redis client later' % x
x+=1
d = defer.Deferred()
d.addCallback(aBlockingRedisCall)
reactor.callLater(1.0,d.callback,x)
return d
else:
print 'got a redis client; doing lookup.. this may take a while'
time.sleep(10) # this is now blocking.. any ideas?
d = defer.Deferred()
d.addCallback(gotFinalResult)
d.callback(x)
return d
def gotFinalResult(x):
return 'final result is %s' % x
def result(res):
print res
def aBlockingMethod():
print 'going to sleep...'
time.sleep(10)
print 'woke up'
def main():
lc = LoopingCall(main_loop)
lc.start(2)
d = defer.Deferred()
d.addCallback(aBlockingRedisCall)
d.addCallback(result)
reactor.callInThread(d.callback, 1)
reactor.run()
if __name__=='__main__':
main()
3 Réponses :
Eh bien, comme le Docs tordus Dites:
Les différés ne font pas le code magiquement pas bloquer p> blockQuote>
Chaque fois que vous utilisez le code de blocage, tel que
SLEEP CODE>, vous devez le différer à un nouveau fil. p>
#!/usr/bin/env python from twisted.internet import reactor,defer, threads from twisted.internet.task import LoopingCall import time def main_loop(): print 'doing stuff in main loop.. do not block me!' def aBlockingRedisCall(x): if x<5: #all connections are busy, try later print '%s is less than 5, get a redis client later' % x x+=1 d = defer.Deferred() d.addCallback(aBlockingRedisCall) reactor.callLater(1.0,d.callback,x) return d else: print 'got a redis client; doing lookup.. this may take a while' def getstuff( x ): time.sleep(3) return "stuff is %s" % x # getstuff is blocking, so you need to push it to a new thread d = threads.deferToThread(getstuff, x) d.addCallback(gotFinalResult) return d def gotFinalResult(x): return 'final result is %s' % x def result(res): print res def aBlockingMethod(): print 'going to sleep...' time.sleep(10) print 'woke up' def main(): lc = LoopingCall(main_loop) lc.start(2) d = defer.Deferred() d.addCallback(aBlockingRedisCall) d.addCallback(result) reactor.callInThread(d.callback, 1) reactor.run() if __name__=='__main__': main()
sur une note connexe, vous pouvez probablement gagner beaucoup à l'aide d'un client REDIS créé spécifiquement pour torsadé, tel que celui-ci: http://github.com/deldotdr/txredis p>
Il existe également un client ReDIS à jour à jour pour torsadé qui prend déjà en charge le nouveau protocole et les nouveaux fonctionnalités de Redis 2.x. Vous devriez définitivement essayer d'essayer. Ça s'appelle Txredisapi. P>
Pour la file d'attente de messages persistants, je recommanderais RestMQ. Un système de file d'attente de messages basé sur REDIS construit sur le cyclone et TXreDisapi. P>
http://github.com/gleicon/restmq p>
acclamations p>