Tornado
一个轻量级的Web框架
简介
1.Tornado在设计之初就考虑到了性能因素,旨在解决C10K问题,这样的设计使得其成为一个拥有非常高性能的框架。
此外,它还拥有处理安全性、用户验证、社交网络以及与外部服务(如数据库和网站API等)进行交互的工具
2.Tornado主要解决高并发问题,在处理高并发上,它采用异步的方式,通常能支持高于10K的并发
tornado安装
1 pip install tornado
简单实用代码示例
# -*- coding: utf-8 -*- __author__ = 'CQ' import textwrap import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web import torndb import os from Tornado import databases_share # 自定义功能更强大的SQL操作 from tornado.options import define, options define("port", default=8888, help="run on the given port", type=int) def use_database(): """ 使用tornado原生的SQL模块 :return: """ db = torndb.Connection(host="127.0.0.1", database="test", user="root", password="123456") a = db.get('select * from node where id=5 ') # get 只能返回一行数据,且是字典格式,返回多行将报错 print(a) b = db.query('select * from node') # query 返回是列表格式的数据,能够返回多条,且每个列表项是一个字典 print(b) exec_str = "insert into user(name,age,gender) values ('%s','%s','%s')" % ("张三", "58", "男") res = db.execute(exec_str) print(res) class ReverseHandler(tornado.web.RequestHandler): def get(self, input): self.write(input[::-1] + ' ') def head(self): self.set_status(200) # 返回指定状态码 class WrapHandler(tornado.web.RequestHandler): def post(self): text = self.get_argument('text') width = self.get_argument('width', 40) self.write(textwrap.fill(text, int(width)) + ' ') def write_error(self, status_code, **kwargs): self.write("Gosh darnit, user! You caused a {0} error. ".format( status_code)) if __name__ == "__main__": tornado.options.parse_command_line() SETTINGS = dict( template_path=os.path.join(os.path.dirname(__file__), "templates"), static_path=os.path.join(os.path.dirname(__file__), "static"), ) urls = [ (r"/reverse/(w+)", ReverseHandler), (r"/wrap", WrapHandler) ] app = tornado.web.Application( handlers=urls, **SETTINGS, ) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start()
使用自定制SQL操作模块
# -*- coding: utf-8 -*- __author__ = 'CQ' import pymysql import logging logger = logging.getLogger(__name__) class MysqlServer(object): """ Tornado通用连接数据库类 用pymysql替代tornado使得操作数据库更加灵活,定制化 """ def __init__(self, db_config): try: self._db_config = db_config self._conn = self.__get_conn() self._cursor = self._conn.curson() except Exception: self.close() logger.exception(u"数据库连接失败") def __get_conn(self): connection = pymysql.connect(host=self._db_config['HOST'], port=self._db_config['PORT'], user=self._db_config['USERNAME'], password=self._db_config['PASSWORD'], db=self._db_config['DB_NAME'], charset=self._db_config['CHAR_SET'], ) connection.ping(True) return connection def ensure_cursor(self): if not self._cursor: if not self._conn: self._conn = self.__get_conn() self._cursor = self._conn.cursor() def run_sql(self, sql): """ 执行完SQL语句需要返回结果 :param sql: :return: """ self.ensure_cursor() self._cursor.execute(sql) # commit只对innodb生效,不加commit的话,修改数据库记录的操作不会生效。 # 如果是myisam引擎的话,不需要commit即可生效 self._conn.commit() return self._cursor.fetchall() def execute_sql(self, sql): """ 执行SQL语句无返回值 :param sql: :return: """ self.ensure_cursor() self._cursor.execute(sql) self._conn.commit() def run_sql_fetchone(self, sql): """ 执行SQL返回一条结果 :param sql: :return: """ self.ensure_cursor() self._cursor.execute(sql) return self._cursor.fetchone() def close(self): if self._cursor: self._cursor.close() if self._conn: self._conn.close() logger.info(u"关闭数据库连接") def test(): settings = { 'HOST': "127.0.0.1", 'PORT': "3306", 'USERNAME': "root", 'PASSWORD': "123456", 'DB_NAME': "test", 'CHAR_SET': "utf8", } db = MysqlServer(settings) sql = "select distinct `node_name` from tb_node" ret = db.run_sql(sql) db.close() return ret if __name__ == "__main__": print(test())
tornado安全相关
1. 使用Cookie正确的用户登陆到网站,保证编写的后台管理程序不被非法访问 2. tornado的cookie使用加密签名来验证cookie的值有没有被服务器软件以外的人修改 3. 因为恶意脚本并不知道安全密钥,所以不能再应用不知情的情况下修改cookie,从而达到安全认证的目的
使用cookie做简单用户验证
# -*- coding: utf-8 -*- __author__ = 'CQ' import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web import tornado.httpclient import os import json from tornado.options import define, options define("port", default=8888, help="run on the given port", type=int) class BaseHandler(tornado.web.RequestHandler): def get_current_user(self): return self.get_secure_cookie("username") # 将用户cookie解密在把值返回 class LoginHandler(BaseHandler): def get(self): self.render('login.html') def post(self): self.set_secure_cookie("username", self.get_argument("username")) self.redirect("/") class WelcomeHandler(BaseHandler): @tornado.web.authenticated # tornado Web自身提供,没有登录时,自动跳转到登录界面,做身份验证用的 def get(self): self.render("welcome.html", username=self.current_user) class LogoutHandler(BaseHandler): def get(self): self.clear_cookie("username") self.redirect("/") if __name__ == "__main__": settings = { "template_path": os.path.join(os.path.dirname(__file__), "templates"), # cookie不会以明文存储在客户端,而是用此字符串加密cookie,然后才存储在客户端 "cookie_secret": "AQAAALudVkKt/AYA0bLPykwXoIBRVYTO", # 当用户没有登录时,tornado会自动跳转的登录URL请求用户登录 "login_url": "/login" } urls = [ (r'/', WelcomeHandler), (r'/login', LoginHandler), (r'/test', WelcomeHandler), (r'/logout', LogoutHandler) ] app = tornado.web.Application( handlers=urls, **settings, ) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start()
项目部署方式
1 fastcgi方式 2 http方法