1、目的
由於有多個程式和指令碼需要對mysql進行讀寫資料庫,每次在指令碼中進行資料庫的連線、用cursor進行操作過於麻煩,因此希望可以有乙個指令碼開放介面,只需要傳入sql語句,就可以返回結果回來。因此有需要乙個可以支援併發量較大的指令碼來進行資料庫操作。以上就要求我的介面具有非同步非阻塞、在結果返回前保持長連線、併發大。因此單純的多執行緒和協程沒辦法滿足要求,就需要用到tornado框架。
2、程式
1)客戶端**(通過requests 呼叫介面)
import reuqests
post = requests.post # post請求方式
def db_query(sql, method='query'):
db_api = '
'db_base = "
dbbase
"db_ret = post(db_api, data=json_encode())
if db_ret.status_code == 200:
if json_decode(db_ret.text)['
status
'] == '
true':
db_ret_data = json_decode(db_ret.text)['
data']
return
else
:
return
else
:
return
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 =
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 = 1234self.db = mysqldb.connect(db_host, user, password, dbbase, port=db_port, cursorclass=mysqldb.cursors.dictcursor)
self.cursor =self.db.cursor()
defquery(self, sql):
self.cursor.execute(sql)
return
self.cursor.fetchall()
defcommit(self, sql):
try:
self.cursor.execute(sql)
self.db.commit()
return
except
exception as e:
self.db.rollback()
return
defclose(self):
self.db.close()
class
servicehandler(tornado.web.requesthandler):
executor = threadpoolexecutor(900) #
必須定義乙個executor的屬性,然後run_on_executor裝飾器才會游泳。
@run_on_executor
#執行緒內執行;query函式被run_on_executor包裹(語法糖),將該函式的執行傳遞給執行緒池executor的執行緒執行,優化了處理耗時性任務,以致達到不阻塞主線程的效果。
defquery(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 #
非同步、協程處理;增加併發量
defpost(self):
data = tornado.escape.json_decode(self.request.body) #
獲取引數,json.loads()解碼
r =
ifnot 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 =
elif data['
method
'] == '
query':
d = yield self.query(data['
dbbase
'], '
query
', data['
sql'
]) r =
elif data['
method
'] == '
commit':
db_r = yield self.query(data['
dbbase
'], '
commit
', data['
sql'
])
if db_r['
status']:
r =
else
: r =
else
: r =
self.write(tornado.escape.json_encode(r))
#寫入返回資訊寫入response
self.finish() #
結束服務
defget(self):
return
self.post()
if__name__ == "
__main__":
(r"/db/api
", servicehandler), #
路由對映
])監聽埠
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非同步學習
why asynchronous tornado是乙個非同步web framework,說是非同步,是因為tornado server與client的網路互動是非同步的,底層基於io event loop。但是如果client請求server處理的handler裡面有乙個阻塞的耗時操作,那麼整體的s...
Tornado非同步模式
先介紹下背景 由於工作需要,前段時間又寫了一段爬蟲去獲取和更新一些資料。之前爬蟲主要用scrapy框架批量爬取一些頁面資料,或者用gevent呼叫目標站點的介面。偶然看到了tornado,聽說這個框架很強大,所以打算這次爬蟲用tornado試試。不足之處,歡迎指正。總的來說,tornado是pyth...
Tornado 非同步socketTCP通訊
tornado 有 tcpclient 和 tcpserver 兩個類,可用於實現 tcp 的客戶端和服務端。事實上,這兩個類都是對iostream的簡單包裝。iostream 是 client 與 server 之間的 tcp 通道。被動等待建立 iostream 的一方是 server,主動找對...