1. 程式人生 > 程式設計 >淺談django url請求與資料庫連線池的共享問題

淺談django url請求與資料庫連線池的共享問題

但凡介紹資料庫連線池的文章,都會說“資料庫連線是一種關鍵的有限的昂貴的資源,這一點在多使用者的網頁應用程式中體現得尤為突出。對資料庫連線的管理能顯著影響到整個應用程式的伸縮性和健壯性,影響到程式的效能指標。資料庫連線池正是針對這個問題提出來的。資料庫連線池負責分配、管理和釋放資料庫連線,它允許應用程式重複使用一個現有的資料庫連線,而不是再重新建立一個;釋放空閒時間超過最大空閒時間的資料庫連線來避免因為沒有釋放資料庫連線而引起的資料庫連線遺漏。這項技術能明顯提高對資料庫操作的效能。”

這句話雖然說得很好,但也很讓人疑惑。比如,多個請求是怎樣共用資料庫連線池啊?

其實,資料庫連線池主要是利用了程式,靜態變數與靜態方法的概念實現的。靜態變數和靜態方法,是程式執行時,就被載入到記憶體中的。該程序中所有對於它的訪問,都是對“唯一”的它的訪問。所以,才能有資料庫連線池被共享的概念。

可以看到,靜態變數a以及靜態方法add,即使類A從未被例項化過,它們也都會被載入到記憶體中。

另外,在python的此次執行(一個程序)中,多次對a的操作,都是對為一個的這個a變數的操作,所以它的值是在被操作後累加的。

這個在我上面簡單的例子中很好理解。那麼如何理解Web應用程式(如django程式)在接到url請求時的場景呢?在多個請求時,他們是如何可以共享資料庫連線池的?

我寫了一個簡單的例子:

Test model,使用了單例模式,它的功能是呼叫sqlalchemy.pool中的資料庫連線池。

而views.py的index方法,則是呼叫Test的getinstance方法獲得它的例項,同時用它的資料庫連線池。

為了看得清楚,我在這個方法中增加列印了當前所屬程序的pid,test和test.connpool資訊。

首先要說明一點,apache在windows和linux中的執行方式不盡相同(windows是兩個httpd程序,一個父程序,一個子程序,子程序裡面多個執行緒處理請求)。在linux中,預設用prefork的方式執行。即一個父程序,多個子程序,這多個子程序負責處理web請求。

如下圖所示:

然後我們嘗試多次url請求(適當變化url,避免快取);並記錄結果:

http://10.67.2.21:8081/ips/
count:3,processid:20016<br/>test:<ipsapp.models.Test object at 0x7f2b1070ac50>,connpool:<sqlalchemy.pool.QueuePool object at 0x7f2b1070ad10>

http://10.67.2.21:8081/ips/?user=kjsdkfjsdf&kljsdlkfjsdf
count:3,processid:20013<br/>test:<ipsapp.models.Test object at 0x7f2b107c6c10>,connpool:<sqlalchemy.pool.QueuePool object at 0x7f2b107c6cd0>

http://10.67.2.21:8081/ips/?user=kjsdkfjsdf&kljsdlkfjsdf&pass=ksjdkjdf
count:3,processid:20018<br/>test:<ipsapp.models.Test object at 0x7f2b103c6c50>,connpool:<sqlalchemy.pool.QueuePool object at 0x7f2b103c6d10>

http://10.67.2.21:8081/ips/?user=123u42i3u4
count:3,connpool:<sqlalchemy.pool.QueuePool object at 0x7f2b1070ad10>

http://10.67.2.21:8081/ips/?user=123u42i3u4&tewstsjdfkjslfj
count:3,connpool:<sqlalchemy.pool.QueuePool object at 0x7f2b107c6cd0>

http://10.67.2.21:8081/ips/?user=passwode
count:3,connpool:<sqlalchemy.pool.QueuePool object at 0x7f2b103c6d10>

http://10.67.2.21:8081/ips/?newiusd=kjsdkjfd&kjsdkjf=ksdjflksjdlkf
count:3,connpool:<sqlalchemy.pool.QueuePool object at 0x7f2b1070ad10>

apache pid Test object QueuePool object
20016 0x7f2b1070ac50 0x7f2b1070ad10
20013 0x7f2b107c6c10 0x7f2b107c6cd0
20018 0x7f2b103c6c50 0x7f2b103c6d10
20016 0x7f2b1070ac50 0x7f2b1070ad10
20013 0x7f2b107c6c10 0x7f2b107c6cd0
20018 0x7f2b103c6c50 0x7f2b103c6d10
20016 0x7f2b1070ac50 0x7f2b1070ad10

我把分屬於不同apache程序處理的請求用顏色標出了,在本例子中,7個請求,分配到了3個apache程序處理。可以看到,被同一個apache子程序處理的請求,是共用同一個test和test.connpool例項的,即他們共享資料庫連線池。

所以,資料庫連線池,對於web請求而言,是屬於同一個apache子程序處理的請求共用一個數據庫連線池。

以上這篇淺談django url請求與資料庫連線池的共享問題就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。