問題背景
最近新的產品開發中,使用了到了Tornado和mysql數據庫。但在基本框架完成之后,我在開發時候發現了一個很奇怪的現象,我在測試時,發現數據庫返回不了結果,於是我在mysql中輸入show processlist,發現連接數很高,我就將目標鎖定在程序代碼和torndb上了。
探索原因
當我kill掉tornado的進程時候,連接數就會被關閉,所以果斷判斷會不會是torndb的原因,導致我連接沒有斷開。於是我猜想會不會是在tornado服務掛掉的時候,mysql的連接沒關。而且我想到我是在測試環境,開啟了DEBUG模式,所以我利用的是tornado的autoreload的功能。
所以問題可能是tornado的autoreload出現了問題,這個時候mysql沒有關閉所有連接,而autoreload 的時候又重新建立了連接,因為python是腳本語言,腳本沒停,api重新加載,那么肯定是重新實例化了application的 時候重新建立了連接,而mysql的實例還在,所以就沒有釋放之前的連接,又疊加了連接。
驗證猜想
為了驗證我的猜想,我又做了以下的測試,同樣開啟兩個終端,一個在tail -f mysqld.log的日志,另一個后台運行tornado,然后我隨便修改了下一個文件,保存后退出,果然連接數翻倍。所以最終問題肯定就是因為mysql的連接沒有釋放了。接下來我做的修改就是在tornado中加了一個hook,在重啟前add_reload_hook中增加了一個release的函數,如下:
def release(): from lib.query import _mysql_server for key in _mysql_server: db = _mysql_server[key] db.close() def run(): application_settings = { 'handlers': urls, 'debug': DEBUG, } application = tornado.web.Application(**application_settings) options.parse_command_line() init_log(options.log_dir) application.listen(options.port) io_loop = tornado.ioloop.IOLoop.instance() # 這段代碼是解決autoreload造成連接數沒有斷開的問題 tornado.autoreload.add_reload_hook(release) tornado.autoreload.start(io_loop) io_loop.start()
