Python Twisted:为什么将延迟回调传递给延迟线程会导致线程突然阻塞?

Python Twisted:为什么将延迟回调传递给延迟线程会导致线程突然阻塞?,python,multithreading,twisted,redis,Python,Multithreading,Twisted,Redis,我尝试将txredis(redis的非阻塞TwistedAPI)用于持久消息队列,但没有成功。我正试图用我正在处理的一个粗糙的项目来设置持久消息队列。我发现,尽管客户端没有阻塞,但它的速度却比可能的慢得多,因为反应器循环中本应是一个事件的事件被分解成数千个步骤 因此,我尝试使用redispy(常规阻塞扭曲api)并将调用包装在延迟线程中。它工作得很好,但是我想在调用redis时执行一个内部延迟,因为我想建立连接池以进一步加快速度 下面是我对twisted文档中延迟线程的一些示例代码的解释,以说明

我尝试将txredis(redis的非阻塞TwistedAPI)用于持久消息队列,但没有成功。我正试图用我正在处理的一个粗糙的项目来设置持久消息队列。我发现,尽管客户端没有阻塞,但它的速度却比可能的慢得多,因为反应器循环中本应是一个事件的事件被分解成数千个步骤

因此,我尝试使用redispy(常规阻塞扭曲api)并将调用包装在延迟线程中。它工作得很好,但是我想在调用redis时执行一个内部延迟,因为我想建立连接池以进一步加快速度

下面是我对twisted文档中延迟线程的一些示例代码的解释,以说明我的用例:

#!/usr/bin/env python
from twisted.internet import reactor,threads
from twisted.internet.task import LoopingCall
import time

def main_loop():
    print 'doing stuff in main loop.. do not block me!'


def aBlockingRedisCall():
    print 'doing lookup... this may take a while'
    time.sleep(10)
    return 'results from redis'

def result(res):
    print res

def main():
    lc = LoopingCall(main_loop)
    lc.start(2)
    d = threads.deferToThread(aBlockingRedisCall)
    d.addCallback(result)
    reactor.run()

if __name__=='__main__':
    main()
下面是我对连接池的修改,它使延迟线程阻塞中的代码:

#!/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()
#/usr/bin/env python
从twisted.internet导入反应器,延迟
从twisted.internet.task导入循环调用
导入时间
def主回路()
在主循环中打印“正在做事情”。。不要挡住我
def aBlockingRedisCall(x):
如果x很好,比如说:

延迟不构成代码 神奇地不阻塞

无论何时使用阻塞代码,例如
sleep
,都必须将其延迟到新线程

#!/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()
#/usr/bin/env python
从twisted.internet导入反应器、延迟、线程
从twisted.internet.task导入循环调用
导入时间
def主回路()
在主循环中打印“正在做事情”。。不要挡住我
def aBlockingRedisCall(x):

如果在相关注释中使用x,您可能会通过使用专门为Twisted创建的Redis客户端获得很多好处,例如:Twisted还有一个最新的Redis客户端,它已经支持Redis 2.x的新协议和功能。你一定要试一试。它叫TXAPI

对于持久消息队列,我建议使用RestMQ。建立在cyclone和txredisapi之上的基于redis的消息队列系统

干杯