1 介绍
大部分python开发都知道Flask
,Djongo
,Tornado
.
而我在进行python端的web开发时,会根据所实现的功能进行技术选型.因为我目前所从事的算法工程化方向,我一般都会采用Tornado
进行web开发.下面呢就说说我为什么选择使用Tornado
.
Tornado的优点和缺点都很明显,下面我们来列举下:
优点:
天生异步(采用
epoll
作为并发模型),在处理http
请求上性能爆表,配合uvloop
作为事件循环,更是锦上添花,轻量级的web框架.
缺点:
生态不够完整,组件不够丰富,在传统web开发时,开发效率较慢.
但是在我所从事的算法工程化方向,不像传统的web开发,比如需要连接数据库,使用mq等相关功能.我们要做的是把算法的能力暴露出去,提供最快的服务访问能力.
而且在python生态上微服务生态基本等于0的,我们可以基于tornado
自己构建一套公司的微服务组件.
下面我们就用代码来构建我们的tornado
环境.
2 环境构建
我目前所用的环境是Python3.6.8
在这里,我就不介绍关于pip
和conda
的相关知识啦!
使用conda安装下面的依赖!
tornado==6.0.2
uvloop==0.12.2
simplejson==3.16.0
3 代码实现
本文代码已上传至github
3.1 TornadoUvloopConfiguration
这个类用来配置uvloop的
import asyncio
import logging
import uvloop
from tornado.platform.asyncio import BaseAsyncIOLoop
logger = logging.getLogger(__name__)
class TornadoUvloopConfiguration(BaseAsyncIOLoop):
def initialize(self, **kwargs):
logger.info("uvloop will init ")
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop = uvloop.new_event_loop()
try:
super(TornadoUvloopConfiguration, self).initialize(
loop, close_loop=True, **kwargs)
except Exception:
loop.close()
raise
3.2 TornadoUVloopHttpServer
这个单例类是我们来实现Tornado HTTP Server.
可以通过参数来设置端口和多进程启动
import logging
import tornado.web
from tornado.httpserver import HTTPServer
from configuration.uvloop_configuration import TornadoUvloopConfiguration
logger = logging.getLogger(__name__)
class TornadoUVloopHttpServer(object):
_instance = None
__http_server = None
@staticmethod
def get_instance(app: tornado.web.Application, port: int, process_num: int = 1):
"""
singleton class
:param app: tornado app
:param port: server port
:param process_num: multi-process num,default 1
:return:
"""
return TornadoUVloopHttpServer(app, port, process_num)
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(TornadoUVloopHttpServer, cls).__new__(cls)
cls._instance.__init(args[0], args[1], args[2])
return cls._instance
@classmethod
def __init(cls, app: tornado.web.Application, port: int, process_num: int):
cls.__http_server = HTTPServer(app)
cls.__http_server.bind(port)
cls.__process_num = process_num
logger.info("http server bind port:%d ,process_num:%d", port, process_num)
def start(cls):
tornado.ioloop.IOLoop.configure(TornadoUvloopConfiguration)
cls.__http_server.start(cls.__process_num)
tornado.ioloop.IOLoop.current().start()
3.3 HelloHandler
这个handler是我们用来进行测试的
from tornado import gen
from tornado.web import RequestHandler
class HelloHandler(RequestHandler):
# 协程装饰器
@gen.coroutine
def get(self):
self.write("Hello, world")
3.4 Main
启动类,并且注册handler
from tornado.web import Application
from common.http_server import TornadoUVloopHttpServer
from handler.hello_handler import HelloHandler
class Main(Application):
def __init__(self, **settings):
super(Main, self).__init__([("/", HelloHandler)], **settings)
if __name__ == '__main__':
TornadoUVloopHttpServer.get_instance(Main(), 6969).start()
4 运行
运行Main.py
后,我们打开浏览器访问127.0.0.1:6969
,看到下面的图片,就说明成功啦!