1、目的

  由于有多个程序和脚本需要对mysql进行读写数据库,每次在脚本中进行数据库的连接、用cursor进行操作过于麻烦,因此希望可以有一个脚本开放接口,只需要传入sql语句,就可以返回结果回来。因此有需要一个可以支持并发量较大的脚本来进行数据库操作。以上就要求我的接口具有异步非阻塞、在结果返回前保持长连接、并发大。因此单纯的多线程和协程没办法满足要求,就需要用到tornado框架。

2、程序

1)客户端代码(通过requests 调用接口)

import reuqests
POST = requests.post # post请求方式
def db_query(sql, method='query'):
db_api = 'http://127.0.0.1:8000/db/api'
db_base = "dbbase"
db_ret = POST(db_api, data=json_encode({'method': method, 'sql': sql, 'dbbase': db_base, 'pwd': 'password123'}))
if db_ret.status_code == 200:
if json_decode(db_ret.text)['status'] == 'True':
db_ret_data = json_decode(db_ret.text)['data']
return {'status': 'ok', 'data': db_ret_data, 'err': ''}
else:
return {'status': 'False', 'data': [], 'err': json_decode(db_ret.text)['data']}
else:
return {'status': 'False', 'data': [], 'err': 'connect error'}

 2)服务端代码(基于tornado框架)

# coding=utf8
import MySQLdb
import MySQLdb.cursors
import tornado
import tornado.ioloop
import tornado.web
import tornado.gen
from tornado.concurrent import run_on_executor
from concurrent.futures import ThreadPoolExecutor class DB_CONFIG:
config = {
'dbbase': ('authentic', 'password'), # 数据库user、password
} class DB:
def __init__(self, dbbase):
user, password = DB_CONFIG.config.get(dbbase, (None, None))
if user == None or password == None:
raise Exception('KeyError', dbbase)
db_host = '192.168.xx.xx'
db_port = 1234 self.db = MySQLdb.connect(db_host, user, password, dbbase, port=db_port, cursorclass=MySQLdb.cursors.DictCursor) self.cursor = self.db.cursor() def query(self, sql):
self.cursor.execute(sql)
return self.cursor.fetchall() def commit(self, sql):
try:
self.cursor.execute(sql)
self.db.commit()
return {'status': True, 'data': ''}
except Exception as e:
self.db.rollback()
return {'status': False, 'data': e} def close(self):
self.db.close() class ServiceHandler(tornado.web.RequestHandler):
executor = ThreadPoolExecutor(900) # 必须定义一个executor的属性,然后run_on_executor装饰器才会游泳。 @run_on_executor # 线程内运行;query函数被run_on_executor包裹(语法糖),将该函数的执行传递给线程池executor的线程执行,优化了处理耗时性任务,以致达到不阻塞主线程的效果。
def query(self, dbname, method, sql):
db = DB(dbname)
ret = ''
if method == 'query':
ret = db.query(sql)
elif method == 'commit':
ret = db.commit(sql)
db.close()
return ret @tornado.web.asynchronous # 保持长连接,直到处理后返回
@tornado.gen.coroutine # 异步、协程处理;增加并发量
def post(self):
data = tornado.escape.json_decode(self.request.body) # 获取参数,json.loads()解码
r = {'status': '', 'data': ''}
if not data.get('pwd', None):
r['status'], r['data'] = ('False', 'not password')
elif not data.get('dbbase', None):
r['status'], r['data'] = ('False', 'not DB select')
else:
if data['pwd'] != 'password123)': # 接口的密码认证
r = {'status': 'False', 'data': 'password error'}
elif data['method'] == 'query': d = yield self.query(data['dbbase'], 'query', data['sql'])
r = {'status': 'True', 'data': d}
elif data['method'] == 'commit': db_r = yield self.query(data['dbbase'], 'commit', data['sql'])
if db_r['status']:
r = {'status': 'True', 'data': 'commit sucessful'}
else:
r = {'status': 'False', 'data': db_r['data']}
else:
r = {'status': 'False', 'data': 'method Invaild'}
self.write(tornado.escape.json_encode(r)) # 写入返回信息写入response
self.finish() # 结束服务 def get(self):
return self.post() if __name__ == "__main__":
application = tornado.web.Application([
(r"/db/api", ServiceHandler), # 路由映射
])
application.listen(8000) # 监听端口
tornado.ioloop.IOLoop.instance().start() # 启动服务

3、请求举例(post请求)

  1) sql语句

 sql = 'select vid from video where status=1 group by vid ORDER BY num ASC limit 100'

   2)客户端调用db_query函数

db_ret = db_query(sql, 'query') # 其中query是数据库操作的方法 query为查询/commit 为insert/update/delete等数据库修改操作时使用

  通过调用db_query传入参数sql语句和操作方式,返回结果或错误内容

基于tornado---异步并发接口的更多相关文章

  1. 异步并发利器:实际项目中使用CompletionService提升系统性能的一次实践

    场景 随着互联网应用的深入,很多传统行业也都需要接入到互联网.我们公司也是这样,保险核心需要和很多保险中介对接,比如阿里.京东等等.这些公司对于接口服务的性能有些比较高的要求,传统的核心无法满足要求, ...

  2. 基于tornado的爬虫并发问题

    tornado中的coroutine是python中真正意义上的协程,与python3中的asyncio几乎是完全一样的,而且两者之间的future是可以相互转换的,tornado中有与asyncio ...

  3. 深入理解yield(三):yield与基于Tornado的异步回调

    转自:http://beginman.cn/python/2015/04/06/yield-via-Tornado/ 作者:BeginMan 版权声明:本文版权归作者所有,欢迎转载,但未经作者同意必须 ...

  4. Python 开源异步并发框架的未来

    http://segmentfault.com/a/1190000000471602 开源 Python 是开源的,介绍的这几个框架 Twisted.Tornado.Gevent 和 tulip 也都 ...

  5. 5.(基础)tornado异步

    终于到了传说中的异步了,感觉异步这个名字听起来就很酷酷的,以前还不是多擅长Python时,就跑去看twisted的源码,结果给我幼小的心灵留下了创伤.反正包括我在内,都知道异步编程很强大,但是却很少在 ...

  6. Python开源异步并发框架

    Python开源异步并发框架的未来 2014年3月30日,由全球最大的中文IT社区CSDN主办的“开源技术大会·” (Open Source Technology Conference ,简称OSTC ...

  7. tornado 异步

    引言 注:正文中引用的 Tornado 代码除特别说明外,都默认引用自 Tornado 4.0.1. tornado.gen 模块是一个基于 python generator 实现的异步编程接口.通过 ...

  8. Tornado异步(2)

    Tornado异步 因为epoll主要是用来解决网络IO的并发问题,所以Tornado的异步编程也主要体现在网络IO的异步上,即异步Web请求. 1. tornado.httpclient.Async ...

  9. 基于tornado实现web camera

    基于tornado实现web camera 近期在学习python.找了一个框架学习,我选择的是tornado.由于其不仅仅是一个web开发框架,其还是一个server,异步事件库,一举多得. 我一直 ...

随机推荐

  1. 工控随笔_24_西门子TIA 博图硬件目录的更新

    西门子博图软件,不但体积庞大,功能也很复杂,与经典的Step7相比,如果不是经常使用,一般都会有一种很难使用的感觉. 而且相比原来的Step7操作有点不太一样.这里简单的说一下硬件目录的更新. 有两种 ...

  2. Python绘制六种可视化图表详解,三维图最炫酷!你觉得呢?

    Python绘制六种可视化图表详解,三维图最炫酷!你觉得呢? 可视化图表,有相当多种,但常见的也就下面几种,其他比较复杂一点,大都也是基于如下几种进行组合,变换出来的.对于初学者来说,很容易被这官网上 ...

  3. kubernetes之kube-proxy运行机制分析

    在kubernetes集群的每个node都会运行一个kube-proxy服务进程,这个进程可用看作Service的透明代理兼负载均衡器.其核心功能是将到某个Service的访问请求转发到后端的多个po ...

  4. Prometheus监控教程——从入门到放弃

    Prometheus的安装还是比较简单的 下载地址如下 https://prometheus.io/download/ 解压,修改配置,运行.默认监听9090端口 [root@localhost ~] ...

  5. 史上最全的中高级Java面试题汇总

    原文链接:https://blog.csdn.net/shengqianfeng/article/details/102572691 memcache的分布式原理 memcached 虽然称为 “ 分 ...

  6. 去掉WARN spring.jpa.open-in-view is enabled by default

    使用springboot jpa,在运行项目时发现一个WARN WARN 11472 --- [ main] aWebConfiguration$JpaWebMvcConfiguration : sp ...

  7. 【miscellaneous】编码格式简介(ANSI、GBK、GB2312、UTF-8、GB18030和 UNICODE)

    转发:http://blog.jobbole.com/30526/ 来源:潜行者m 的博客 编码一直是让新手头疼的问题,特别是 GBK.GB2312.UTF-8 这三个比较常见的网页编码的区别,更是让 ...

  8. Kubernetes+Istio

    Kubernetes+Istio   微服务.SpringCloud.k8s.Istio杂谈   一.微服务与SOA “微服务”是一个名词,没有这个名词之前也有“微服务”,一个朗朗上口的名词能让大家产 ...

  9. Linux字符设备驱动基本结构

    1.Linux字符设备驱动的基本结构 Linux系统下具有三种设备,分别是字符设备.块设备和网络设备,Linux下的字符设备是指只能一个字节一个字节读写的设备,不能随机读取设备内存中某一数据,读取数据 ...

  10. day18——re正则表达式

    day18 re模块--正则表达式 匹配方法 findall():从字符串中全部查找内容,返回一个列表 s = "meet_宝元_meet" print(re.findall(&q ...