복붙노트

[REDIS] 토네이도의 레디 스 연결을 처리 할 수있는 적절한 방법은 무엇입니까? (비동기 - 출판 / 하위)

REDIS

토네이도의 레디 스 연결을 처리 할 수있는 적절한 방법은 무엇입니까? (비동기 - 출판 / 하위)

내가 Brukva 사이트에서 샘플 애플리케이션에서 보았을 때 나는 asyc 클라이언트 Brukva 내 토네이도 응용 프로그램과 함께 레디 스를 사용하고, 그들은 웹 소켓에서 "초기화"방법에 새로운 연결을 만들고있다

class MessagesCatcher(tornado.websocket.WebSocketHandler):
    def __init__(self, *args, **kwargs):
        super(MessagesCatcher, self).__init__(*args, **kwargs)
        self.client = brukva.Client()
        self.client.connect()
        self.client.subscribe('test_channel')

    def open(self):
        self.client.listen(self.on_message)

    def on_message(self, result):
        self.write_message(str(result.body))

    def close(self):
        self.client.unsubscribe('test_channel')
        self.client.disconnect()

웹 소켓하지만 어떻게 일반적인 토네이도 RequestHandler를 포스트 방법을 처리하는 방법의 경우의 벌금 긴 폴링 작업 (모델을 게시 - 구독) 말한다. 내가 업데이트 핸들러의 모든 것들을 방법에 새로운 클라이언트 connetion을 만드는 중이라서이 올바른 접근 방식이다 ?? 나는 레디 스 콘솔에서이 옵션을 선택하면 나는 모든 새 게시물 작업에서 증가하는 고객을 참조하십시오.

여기에 내 코드의 샘플입니다.

c = brukva.Client(host = '127.0.0.1')
c.connect()

class MessageNewHandler(BaseHandler):
    @tornado.web.authenticated
    def post(self):

        self.listing_id = self.get_argument("listing_id")
        message = {
            "id": str(uuid.uuid4()),
            "from": str(self.get_secure_cookie("username")),
            "body": str(self.get_argument("body")),
        }
        message["html"] = self.render_string("message.html", message=message)

        if self.get_argument("next", None):
            self.redirect(self.get_argument("next"))
        else:
            c.publish(self.listing_id, message)
            logging.info("Writing message : " + json.dumps(message))
            self.write(json.dumps(message))

    class MessageUpdatesHandler(BaseHandler):
        @tornado.web.authenticated
        @tornado.web.asynchronous
        def post(self):
            self.listing_id = self.get_argument("listing_id", None)
            self.client = brukva.Client()
            self.client.connect()
            self.client.subscribe(self.listing_id)
            self.client.listen(self.on_new_messages)

        def on_new_messages(self, messages):
            # Closed client connection
            if self.request.connection.stream.closed():
                return
            logging.info("Getting update : " + json.dumps(messages.body))
            self.finish(json.dumps(messages.body))
            self.client.unsubscribe(self.listing_id)


        def on_connection_close(self):
            # unsubscribe user from channel
            self.client.unsubscribe(self.listing_id)
            self.client.disconnect()

비슷한 경우에 대한 몇 가지 예제 코드를 제공하는 경우 내가 주셔서 감사합니다.

해결법

  1. ==============================

    1.조금 늦었지만 나는 토네이도 레디 스를 사용하고있다. 이 토네이도의 ioloop과 tornado.gen 모듈과 함께 작동

    조금 늦었지만 나는 토네이도 레디 스를 사용하고있다. 이 토네이도의 ioloop과 tornado.gen 모듈과 함께 작동

    tornadoredis 설치

    그것은 핍에서 설치할 수 있습니다

    pip install tornadoredis
    

    또는 setuptools에와

    easy_install tornadoredis
    

    하지만 당신은 정말 그렇게해서는 안된다. 또한 저장소를 복제하고 추출 할 수 있습니다. 그런 다음 실행

    python setup.py build
    python setup.py install
    

    연결 레디 스에

    다음 코드는 main.py 또는 동등한 간다

    redis_conn = tornadoredis.Client('hostname', 'port')
    redis_conn.connect()
    

    redis.connect 한 번만 호출됩니다. 그것은 메인 ioloop을 시작하기 전에 호출 할 필요가 있으므로, 차단 호출입니다. 같은 연결 개체는 모든 핸들러 사이에 공유됩니다.

    당신은 같은 응용 프로그램 설정에 추가 할 수 있습니다

    settings = {
        redis = redis_conn
    }
    app = tornado.web.Application([('/.*', Handler),],
                                  **settings)
    

    사용 tornadoredis

    연결이 self.settings [ '레디 스'] 또는 그것이 BaseHandler 클래스의 속성으로서 첨가 될 수있는 처리기를 사용할 수있다. 요청 핸들러 클래스 및 액세스 속성을 서브 클래스입니다.

    class BaseHandler(tornado.web.RequestHandler):
    
        @property
        def redis():
            return self.settings['redis']
    

    레디 스와 통신하려면 tornado.web.asynchronous과 tornado.gen.engine의 장식이 사용됩니다

    class SomeHandler(BaseHandler):
    
        @tornado.web.asynchronous
        @tornado.gen.engine
        def get(self):
            foo = yield gen.Task(self.redis.get, 'foo')
            self.render('sometemplate.html', {'foo': foo}
    

    추가 정보

    더 많은 예제 및 연결 풀링 및 파이프 라인과 같은 다른 기능은 GitHub의의의 repo에서 찾을 수 있습니다.

  2. ==============================

    2.당신은 당신의 응용 프로그램에서 연결을 풀 것이다. 자동으로이 기능을 지원하지 않습니다 brukva처럼 보이기 때문에 (레디 스-평이를 지원하지만이 토네이도 잘 이동하지 않도록 자연 차단), 당신은 당신의 자신의 연결 풀을 작성해야합니다.

    당신은 당신의 응용 프로그램에서 연결을 풀 것이다. 자동으로이 기능을 지원하지 않습니다 brukva처럼 보이기 때문에 (레디 스-평이를 지원하지만이 토네이도 잘 이동하지 않도록 자연 차단), 당신은 당신의 자신의 연결 풀을 작성해야합니다.

    패턴이 있지만, 아주 간단합니다. 이 라인을 따라 뭔가 (이 실제 작동 코드가 아닙니다)

    class BrukvaPool():
    
        __conns = {}
    
    
        def get(host, port,db):
            ''' Get a client for host, port, db '''
    
            key = "%s:%s:%s" % (host, port, db)
    
            conns = self.__conns.get(key, [])
            if conns:
                ret = conns.pop()
                return ret
            else:
               ## Init brukva client here and connect it
    
        def release(client):
            ''' release a client at the end of a request '''
            key = "%s:%s:%s" % (client.connection.host, client.connection.port, client.connection.db)
            self.__conns.setdefault(key, []).append(client)
    

    그것은 좀 더 까다로운 일이 될 수 있지만, 그 주요 생각이다.

  3. from https://stackoverflow.com/questions/8466838/what-is-the-proper-way-to-handle-redis-connection-in-tornado-async-pub-sub by cc-by-sa and MIT license