Tornado
一个轻量级的Web框架
简介
1.Tornado在设计之初就考虑到了性能因素,旨在解决C10K问题,这样的设计使得其成为一个拥有非常高性能的框架。
此外,它还拥有处理安全性、用户验证、社交网络以及与外部服务(如数据库和网站API等)进行交互的工具
2.Tornado主要解决高并发问题,在处理高并发上,它采用异步的方式,通常能支持高于10K的并发
tornado安装
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="")
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')" % ("张三", "", "男")
res = db.execute(exec_str)
print(res) class ReverseHandler(tornado.web.RequestHandler): def get(self, input):
self.write(input[::-1] + '\n') 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)) + '\n') def write_error(self, status_code, **kwargs):
self.write("Gosh darnit, user! You caused a {0} error.\n".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': "",
'USERNAME': "root",
'PASSWORD': "",
'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()
项目部署方式
fastcgi方式
http方法