tornado, python的高并发微服务,从入门到部署上线

文章目录

      • 1.介绍
      • 2.安装和使用
      • 3.Tornado web 主要模块
      • 4.三种启动方式
        • 第一种启动方式:单进程
        • 第二种启动方式:多进程
        • 第三种启动方式:多进程
      • 5.编写高并发服务

1.介绍

使用python编写的网络框架和高性能的异步网络库
使用大量连接、长轮询、websockets应用

  • 优势:微服务、高性能、异步支持
  • 缺点:轮子少不像Django、Flask等框架有大量插件支持;缺少最佳实践,使用的公司不多,学习资料少

使用场景
构建微服务,不适合复杂的CMS(内容管理系统)应用;适合构建网站或者App后端微服务

学习资料

  • 官方文档:https://www.tornadoweb.org/en/stable/;
  • github:https://github.com/tornadoweb/tornado
  • 书:《Introduction to Tornado》

2.安装和使用

安装: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

3.Tornado web 主要模块

主要模块
tornado.web ApplicationRequestHandler 类处理http请求
tornado.template 模版渲染
tornado.routing 处理路由

HTTP服务器和客户端模块
tornado.httpserver 非阻塞HTTP客户端
tornado.httpclient 异步HTTP客户端

异步networking
tornado.ioloop 事件循环
tornado.iostream 非阻塞socket封装
tornado.tcpservertornado.tcpclient

协程和并发
tornado.gen 协程模块
tornado.locks/tornado.queues 同步、协程队列模块

  • 阻塞和非阻塞,描述的是请求方(即生产者)的状态
  • 同步与非同步描述的是事件处理者(即消费者)的处理方式

4.三种启动方式

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()  # 开始事件

我使用第三种方式部署服务

5.编写高并发服务

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()  # 开始事件

你可能感兴趣的:(微服务,Django)