我目前正在爲我的應用程序開發的API後端運行Flask + SQLAlchemy + uWSGI + nginx堆棧。 我試圖通過使用ApacheBench並向服務器上的端點發送不同數量的併發請求來查看我的服務器上可以擁有的最大併發連接數。提高SQLAlchemy的性能?
此端點將採用JSON請求正文,提取某些值,運行查詢,然後根據查詢結果返回JSON響應。
我跑了的基本測試,併發請求 10個請求,我的平均響應時間爲60毫秒。
運行與10併發請求的另一測試爲100個請求返回的150毫秒的平均,100併發請求 1000返回1500毫秒和500 併發請求返回周圍7000-9000ms。
Concurrency Level: 500
Time taken for tests: 38.710 seconds
Complete requests: 5000
Failed requests: 0
Total transferred: 1310000 bytes
Total body sent: 1105000
HTML transferred: 110000 bytes
Requests per second: 129.17 [#/sec] (mean)
Time per request: 3870.986 [ms] (mean)
Time per request: 7.742 [ms] (mean, across all concurrent requests)
Transfer rate: 33.05 [Kbytes/sec] received
27.88 kb/s sent
60.93 kb/s total
Connection Times (ms)
min mean[+/-sd] median max
Connect: 24 63 185.1 25 3025
Processing: 161 3737 2778.7 3316 26719
Waiting: 157 3737 2778.7 3316 26719
Total: 187 3800 2789.7 3366 26744
Percentage of the requests served within a certain time (ms)
50% 3366
66% 4135
75% 4862
80% 5711
90% 7449
95% 9158
98% 11794
99% 13373
100% 26744 (longest request)
延遲似乎是線性增加這是有道理的,但它似乎很快增加了太快。在做了很多修補和分析之後,我發現瓶頸在於查詢。
在基準測試開始時,查詢會在10-50毫秒內處理並快速返回,但會迅速增加,並且在某些情況下可以看到10000-15000毫秒的延遲。
我無法弄清楚爲什麼數據庫減慢了這麼多,特別是因爲它是空的(禁止測試數據)。
我試着在沒有連接池的情況下運行應用程序,結果顯示延遲下降(7-9s到5-6s)。我不認爲這是可能的,因爲我讀的所有內容都建議使用連接池,這會讓事情變得更快,因爲您可以避免每次發出請求時建立新連接的開銷。
我還試驗了增加連接池大小(從默認的5到50),並且減少的延遲甚至比無池設置(5-6s到3-4s)還要多。
Concurrency Level: 500
Time taken for tests: 4.842 seconds
Complete requests: 836
Failed requests: 0
Non-2xx responses: 679
Total transferred: 272673 bytes
Total body sent: 294593
HTML transferred: 126353 bytes
Requests per second: 172.67 [#/sec] (mean)
Time per request: 2895.662 [ms] (mean)
Time per request: 5.791 [ms] (mean, across all concurrent requests)
Transfer rate: 55.00 [Kbytes/sec] received
59.42 kb/s sent
114.42 kb/s total
Connection Times (ms)
min mean[+/-sd] median max
Connect: 24 170 273.1 93 1039
Processing: 25 665 1095.2 149 4753
Waiting: 25 665 1095.2 149 4753
Total: 51 835 1123.9 279 4786
Percentage of the requests served within a certain time (ms)
50% 279
66% 487
75% 1050
80% 1059
90% 2935
95% 3658
98% 4176
99% 4337
100% 4786 (longest request)
等待時間仍然是非常高的(3-4秒的API似乎通過任何標準不合理),而我試圖找出我怎麼能更加減少它。答案只是更多的連接?
注: 我正在4個ram和四核處理器的服務器上運行4個uWSGI進程,每個進程有100個線程。 我正在使用psycopg2-cffi適配器進行連接,並且該應用程序正在PyPy上運行。
嘗試調整過程的數量。它會以犧牲資源爲每個進程創建一個連接池。後續步驟:如果在一臺服務器上運行:單獨分貝和燒瓶。最後的最後時刻:現在4Gb並不多。只有一件事可以替代RAM,更多的RAM。 –
@KlausD。 :有多少個進程太多?我知道gunicorn國家2xcores + 1是建議的金額,但uWSGI文件聲明,沒有他們的等值。 也是內存相關的這個問題?我知道通常當人們談論數據庫延遲時,他們通過緩存來解決它,這自然需要更多的RAM,但這看起來像是連接問題。當然,我不太熟悉它,所以你可能是對的,但這是我迄今爲止收集的。 – lonewaft
進程數量沒有最終公式。特別是當您有超線程技術時,每個物理內核有兩個「虛擬」內核,性能可能因負載分配方式以及應用程序的工作方式而異。你將不得不嘗試找到最好的價值。 RAM對於數據庫來說總是很重要。這適用於數量和速度。還有更多的進程需要更多的RAM。 –