【问题标题】:Twisted: Advise on using txredisapi library requiredTwisted:建议使用所需的 txredisapi 库
【发布时间】:2023-12-28 20:38:02
【问题描述】:

下面我提供了一个代码示例,它使用来自 Redis 的数据简单地响应 HTTP GET 请求:

请求: http://example.com:8888/?auth=zefDWDd5mS7mcbfoDbDDf4eVAKb1nlDmzLwcmhDOeUc 回复: get: u'"True"'

此代码的目的是作为 REST 服务器(这就是我使用lazyConnectionPool 的原因)响应请求,并使用来自 Redis 的数据(读/写)。

我需要做什么:

  1. 在 IndexHandler 的 render_GET 内向 Redis 运行多个请求(如 GET、HMGET、SET 等)
  2. 在 IndexHandler 的 render_GET 内的事务中运行多个请求

我尝试了多种方法来做到这一点(包括来自 txredisapi 库的示例),但由于缺乏经验未能做到这一点。能否请您就问题 1) 和 2) 提供建议。

提前致谢。

import txredisapi as redis

from twisted.application import internet
from twisted.application import service
from twisted.web import server
from twisted.web.resource import Resource


class Root(Resource):
    isLeaf = False


class BaseHandler(object):
    isLeaf = True

    def __init__(self, db):
        self.db = db
        Resource.__init__(self)


class IndexHandler(BaseHandler, Resource):
    def _success(self, value, request, message):
        request.write(message % repr(value))
        request.finish()

    def _failure(self, error, request, message):
        request.write(message % str(error))
        request.finish()

    def render_GET(self, request):
        try:
            auth = request.args["auth"][0]
        except:
            request.setResponseCode(404, "not found")
            return ""

        d = self.db.hget(auth, 'user_add')
        d.addCallback(self._success, request, "get: %s\n")
        d.addErrback(self._failure, request, "get failed: %s\n")
        return server.NOT_DONE_YET


# Redis connection parameters
REDIS_HOST = '10.10.0.110'
REDIS_PORT = 6379
REDIS_DB = 1
REDIS_POOL_SIZE = 1
REDIS_RECONNECT = True

# redis connection
_db = redis.lazyConnectionPool(REDIS_HOST, REDIS_PORT, REDIS_DB, REDIS_POOL_SIZE)

# http resources
root = Root()
root.putChild("", IndexHandler(_db))

application = service.Application("web")
srv = internet.TCPServer(8888, server.Site(root), interface="127.0.0.1")
srv.setServiceParent(application)

【问题讨论】:

  • 这段代码看起来不错。我没有运行它,但它有什么问题?
  • 提供的代码绝对是功能性的,与当前的实现没有任何问题。我需要用以下方法扩展它: (i) 在 IndexHandler 的 render_GET 中运行多个对 Redis 的请求(如 GET、HMGET、SET 等); (ii) 在 IndexHandler 的 render_GET 内的事务中运行多个请求

标签: python redis twisted


【解决方案1】:

关于第一个问题:

有几种方法可以概括为在单个 HTTP 请求中发出多个数据库请求。

例如,您可以发出多个请求:

d1 = self.db.hget(auth, 'user_add')
d2 = self.db.get('foo')

然后,您可以在所有这些同时请求完成时触发回调(请参阅twisted.internet.defer.DeferredList)。

如果您需要顺序请求,您也可以使用inlineCallbacks。例如:

@inlineCallbacks
def do_redis(self):
    foo = yield self.db.get('somekey')
    bar = yield self.db.hget(foo, 'bar') # Get 'bar' field of hash foo

但是您需要阅读更多关于将inlineCallbackstwisted.web 结合起来的信息(您应该查找有关该主题的SO questions)。

关于问题2:

如果不使用inlineCallbacks,交易真的很难看。在txredisapi homepage 有一个示例,它使用inlineCallbacks 显示它。

【讨论】:

  • 谢谢@Max,看来我已经找到了与您使用inlineCallbacks 描述的相同的解决方案。我认为它对我有用,我一定会尝试使用DeferredList 解决方案。
  • 不客气,@PavelKlymenko。恕我直言,DeferredList 少量可用,但从长远来看,inlineCallbacks 值得代码简洁。
  • 我认为你是对的@Max。通过inlineCallbacks 实现。再次感谢。
  • 这里是 txredisapi 的作者。我想说inlineCallbacks 绝对是要走的路。