Tornado中具有多个进程的异步连接池

时间:2016-03-07 08:57:19

标签: asynchronous elasticsearch tornado connection-pooling pool

我同时使用 Tornado 4.2.1 tornadoes 2.4.1 库来查询我的Elasticsearch数据库,并且我正在寻找一种方法初始化连接池以在多进程服务中的多个RequestHandler实例之间共享。

有可能吗?是否有针对龙卷风的特定库来做到这一点?

提前致谢

1 个答案:

答案 0 :(得分:7)

由于tornado-es只是一个HTTP客户端,因此它使用AsyncHTTPClient中的ESConnection。除非指定Connection: keep-alive标头,否则每次请求都会建立新的TCP连接

conn = ESConnection()
conn.httprequest_kwargs['headers'] = {'Connection': 'keep-alive'}

我没有测试过,但应该可以使用。我在ruby中使用了类似的设置(使用patron http客户端),并且效果很好

下一件事

AsyncHTTPClient限制了每个ioloop的最大并发请求数(fetch)。每个达到限制的请求都在内部排队。

您可能希望增加全局限制:

AsyncHTTPClient.configure(None, max_clients=50)

或将客户端与其自己的限制(force_instance)分开:

from tornadoes import ESConnection
from tornado.httpclient import AsyncHTTPClient

class CustomESConnection(ESConnection):

    def __init__(self, , host='localhost', port='9200', io_loop=None, protocol='http', max_clients=20):
        super(CustomESConnection, self).__init__(host, port, io_loop, protocol)
        self.client = AsyncHTTPClient(force_instance=True, max_clients=max_clients)

最后

要重用相同的ESConnection,您可以在Application中创建它,因为每个请求都可以使用该应用程序(RequestHandler)

from tornado.web import Application, RequestHandler
from tornadoes import ESConnection

class MainHandler(RequestHandler):
    def get(self):
        yield self.application.es.search('something')


class MyApp(Application):

    def __init__(self, *args, **kwargs):
        super(MyApp, self).__init__(*args, **kwargs)

        self.es = ESconnection()

if __name__ == "__main__":
    application = MyApp([
        (r"/", MainHandler),
    ])
    application.listen(8888)
    tornado.ioloop.IOLoop.current().start()

<强>多进程

实际上没有简单的方法。常见的方法是pooler,主要用于需要持久连接时,如数据库(postgres的pgbouncer)或高负载服务的优化。

你必须写一个pooler,一个网关应用程序来es

subprocess1 
           \  (http, zmq, ...)
            \            
              > pooler (some queue and tornadoes api) - http -> elastisearch
            /
           /
subprocess2

子进程可以通过HTTP,ØMQ(有很多例子甚至是更简单的)或者IPC的一些实现(sockects,......)与pooler进行通信。