使用python编写的网络框架和高性能的异步网络库
使用大量连接、长轮询、websockets应用
使用场景
构建微服务,不适合复杂的CMS(内容管理系统)应用;适合构建网站或者App后端微服务
学习资料
安装:pip install tornado
下载源码学习示例代码:git clone https://github.com/tornadoweb/tornado.git
(没有git的话先安装git,yum -y install git
)
官网上拷hello,word代码
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
1.编写一个hello world 应用 app.py,以上代码
2.使用python app.py 启动tornado应用
3.使用curl或者浏览器验证:curl http://127.0.0.1:8888
主要模块
tornado.web Application
和 RequestHandler
类处理http请求
tornado.template
模版渲染
tornado.routing
处理路由
HTTP服务器和客户端模块
tornado.httpserver
非阻塞HTTP客户端
tornado.httpclient
异步HTTP客户端
异步networking
tornado.ioloop
事件循环
tornado.iostream
非阻塞socket封装
tornado.tcpserver
和 tornado.tcpclient
协程和并发
tornado.gen
协程模块
tornado.locks/tornado.queues
同步、协程队列模块
- 阻塞和非阻塞,描述的是请求方(即生产者)的状态
- 同步与非同步描述的是事件处理者(即消费者)的处理方式
app.listen()这个方法只能在单进程模式中使用。
对于app.listen()与方式二中的手动创建HTTPServer实例这两种方式,建议大家先使用后者即创建HTTPServer实例的方式,因为其对于理解tornado web应用工作流程的完整性有帮助,便于大家记忆tornado开发的模块组成和程序结构;在熟练使用后,可以改为简写。
import tornado.web # web服务
import tornado.ioloop # I/O 时间循环
import tornado.httpserver # 新引入httpserver模块,单线程的http服务
class Mainhandler(tornado.web.RequestHandler):
def get(self):
self.write("hello world!")
# 建立路由表
app = tornado.web.Application([
(r"/index", Mainhandler),
])
if __name__ == "__main__":
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(8000)
# tornado.ioloop.IOLoop.current().start()
tornado.ioloop.IOLoop.instance().start() # 开始事件
在这一修改版本中,我们引入了tornado.httpserver模块,顾名思义,它就是tornado的HTTP服务器实现。
我们创建了一个HTTP服务器实例http_server,因为服务器要服务于我们刚刚建立的web应用,将接收到的客户端请求通过web应用中的路由映射表引导到对应的handler中,所以在构建http_server对象的时候需要传出web应用对象app。http_server.listen(8000)将服务器绑定到8000端口。
实际上一版代码中app.listen(8000)正是对这一过程的简写。
```python
import tornado.web # web服务
import tornado.ioloop # I/O 时间循环
import tornado.httpserver # 新引入httpserver模块,单线程的http服务
class Mainhandler(tornado.web.RequestHandler):
def get(self):
self.write("hello world!")
# 建立路由表
app = tornado.web.Application([
(r"/index", Mainhandler),
])
if __name__ == "__main__":
http_server = tornado.httpserver.HTTPServer(app)
http_server.bind(8000)
http_server.start(3)
# tornado.ioloop.IOLoop.current().start()
tornado.ioloop.IOLoop.instance().start() # 开始事件
http_server.bind(port)方法是将服务器绑定到指定端口。
http_server.start(num_processes=1)方法指定开启几个进程,参数num_processes默认值为1,即默认仅开启一个进程;如果num_processes为None或者<=0,则自动根据机器硬件的cpu核芯数创建同等数目的子进程;如果num_processes>0,则创建num_processes个子进程。
前面写的http_server.listen(8000)实际上就等同于:http_server.bind(8000) http_server.start(1)这两行代码。
import tornado.web # web服务
import tornado.ioloop # I/O 时间循环
import tornado.httpserver # 新引入httpserver模块,单线程的http服务
class Mainhandler(tornado.web.RequestHandler):
def get(self):
self.write("hello world!")
# 建立路由表
app = tornado.web.Application([
(r"/index", Mainhandler),
])
if __name__ == "__main__":
sockets = tornado.netutil.bind_sockets(8888)
tornado.process.fork_processes(0) # 10
http_server = tornado.httpserver.HTTPServer(app)
http_server.add_sockets(sockets)
# tornado.ioloop.IOLoop.current().start()
tornado.ioloop.IOLoop.instance().start() # 开始事件
我使用第三种方式部署服务
get_data有方法里面有多个数据接口,使用协程可以提高服务的并发能力
# -*-coding:utf8-*-
"""
-----
"""
import tornado.ioloop
import tornado.web
import tornado.httpserver
import tornado.options
from tornado.concurrent import run_on_executor
import http.client
from concurrent.futures import ThreadPoolExecutor
class MainHandler(tornado.web.RequestHandler):
executor = ThreadPoolExecutor(10) # 起线程池,由当前RequestHandler持有
@tornado.gen.coroutine
def get(self):
data = yield self.get_data(parameters)
@run_on_executor
def get_data(self, appId, userId, Client_parameters):
return data
class TestHandler(tornado.web.RequestHandler):
def get(self):
self.write('ok')
def make_app():
return tornado.web.Application([
(r"/", MainHandler), (r"/test", TestHandler)
])
if __name__ == "__main__":
app = make_app()
sockets = tornado.netutil.bind_sockets(8000)
tornado.process.fork_processes(0) # 10
http_server = tornado.httpserver.HTTPServer(app)
http_server.add_sockets(sockets)
tornado.ioloop.IOLoop.instance().start() # 开始事件