我同时使用 Tornado 4.2.1 和 tornadoes 2.4.1 库来查询我的Elasticsearch数据库,并且我正在寻找一种方法初始化连接池以在多进程服务中的多个RequestHandler实例之间共享。
有可能吗?是否有针对龙卷风的特定库来做到这一点?
提前致谢
答案 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进行通信。