如何在Tornado中使用Python3.4进行异步MySQL操作?
我现在使用的是Python3.4,想在Tornado中使用异步的MySQL客户端。我找到了一款叫torndb的工具,但看了它的源代码后,我觉得它不能进行异步的MySQL操作,因为它只是对MySQLdb这个包进行了封装。
那么,有没有办法在Tornado中实现异步的MySQL操作呢?
1 个回答
3
使用MySQL和Tornado的标准方法是用一组单独的进程来和MySQL沟通,然后用异步的HTTP请求来和这些进程交流(你可以参考这个链接中的第二个答案)。这些进程可以在同一台机器上,也可以在其他地方的应用服务器上。下面是一个简单的例子:
import json, sys, time
from MySQLdb import connect, cursors
from tornado import gen, httpclient, web, netutil, process, httpserver, ioloop
class BackendHandler(web.RequestHandler):
def get(self):
time.sleep(1) # simulate longer query
cur = connect(db='tornado', user='root').cursor(cursors.DictCursor)
cur.execute("SELECT * FROM foo")
self.write(json.dumps(list(cur.fetchall())))
class FrontendHandler(web.RequestHandler):
@gen.coroutine
def get(self):
http_client = httpclient.AsyncHTTPClient(max_clients=500)
response = yield http_client.fetch("http://localhost:8001/foo")
self.set_header("Content-Type", 'application/json')
self.write(response.body)
if __name__ == "__main__":
number_of_be_tasks = int(sys.argv[1]) if len(sys.argv) > 1 else 20
number_of_fe_tasks = int(sys.argv[2]) if len(sys.argv) > 2 else 1
fe_sockets = netutil.bind_sockets(8000) # need to bind sockets
be_sockets = netutil.bind_sockets(8001) # before forking
task_id = process.fork_processes(number_of_be_tasks + number_of_fe_tasks)
if task_id < number_of_fe_tasks:
handler_class = FrontendHandler
sockets = fe_sockets
else:
handler_class = BackendHandler
sockets = be_sockets
httpserver.HTTPServer(web.Application([(r"/foo", handler_class)])
).add_sockets(sockets)
ioloop.IOLoop.instance().start()
不过,如果你的网页服务器主要是直接和MySQL对话,那么Tornado的优势就不大了(因为你需要的进程数量和你想要的同时连接数是一样的)。在这种情况下,使用nginx+uwsgi+python可能会更好。Tornado真正擅长的是和多个后端服务器进行HTTP通信,可能还可以并行处理。