1. 程式人生 > >在tornado中使用非同步mysql操作

在tornado中使用非同步mysql操作

在使用tornado框架進行開發的過程中,發現tornado的mysql資料庫操作並不是一步的,造成了所有使用者行為的堵塞.tornado本身是一個非同步的框架,要求所有的操作都應該是非同步的,但是資料庫這一層就把整個伺服器都拖住了.

##查詢到的解決辦法:

  1. 使用非同步的mysql操作庫. 查找了一下,有兩個比較完善的非同步操作庫
    一個是AsyncTorndb,國人自己寫的非同步操作,看了一下,好像不錯的樣子,但是沒有響應的測試用例,不敢用.

    一個是Tornado-MySQL是對PyMySQL的非同步化的一個庫,測試用例,文件,都比較齊全,可以嘗試使用.

2.仿照(torngas)[

https://github.com/mqingyn/torngas]的非同步執行緒池,使用tornado的concurrent.run_on_executor裝飾器對資料庫操作進行非同步化

3.使用任務佇列,太過麻煩,對之前的程式碼修改過大,不使用該方案

  • 在使用Tornado-MySQL過程中,發現對現有程式碼更改太過嚴重,放棄,使用了非同步執行緒池的方式.做到最小的程式碼更改以及非同步資料庫操作的實現

##如何使用非同步執行緒池concurrent.run_on_executor

  1. 在原先的同步的資料庫執行的方法新增@concurrent.run_on_executor裝飾器,如以下例子:

    1
    2
    3
    4
    5
    6
    7
    @concurrent.run_on_executor
    def runSql(self):
    t = time.time()
    db = client.conn()
    db.execute('''select * from TABLE_CONSTRAINTS join (CHARACTER_SETS,STATISTICS)''')
    db.close()
    return time.time() - t
  1. 在呼叫該方法的函式使用yield tornado.gen.Task(functionName) 呼叫上面的修改的方法,並且為主函式新增@tornado.gen.engine裝飾器,如以下例子(tordona框架中的requestHander中的get方法):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @tornado.web.asynchronous
    @tornado.gen.engine
    def get(self, *args, **kwargs):
    # print self.get_query_argument("test11")
    time = yield tornado.gen.Task(self.runSql)
    print time
    self.write(unicode(time))
    print "over"
    self.finish()

    *使用@tornado.web.asynchronous 裝飾器取消requestHander的自動finish,不然無法等待非同步sql執行完畢再返回資料