記一次線上gc調(diào)優(yōu)的過程
近期線上我們一個后臺管理系統(tǒng)運行特別慢,而且經(jīng)常出現(xiàn)504超時的情況。對于這種情況我們本能的認為可能是代碼有性能問題,可能有死循環(huán)或者是數(shù)據(jù)庫調(diào)用次數(shù)過多導致接口運行過慢。應(yīng)領(lǐng)導要求,我們將主站中進行性能測試的框架代碼添加到該后臺管理系統(tǒng)中。上線運行一段時間后,查看相關(guān)日志可以看到如下分析日志:
mysql 數(shù)據(jù)庫鏈接數(shù)優(yōu)化:
查看mysql連接數(shù)狀態(tài)
.mysql> show status like ‘Threads%’;
+——————-+——-+
| Variable_name | Value |
+——————-+——-+
| Threads_cached | 58 |
| Threads_connected | 57 | ###這個數(shù)值指的是打開的連接數(shù)
| Threads_created | 3676 |
| Threads_running | 4 | ###這個數(shù)值指的是激活的連接數(shù),這個數(shù)值一般遠低于connected數(shù)值
+——————-+——-+
Threads_connected 跟show processlist結(jié)果相同,表示當前連接數(shù)。準確的來說,Threads_running是代表當前并發(fā)數(shù)
查詢數(shù)據(jù)庫當前設(shè)置的最大連接數(shù)
2.mysql> show variables like ‘%max_connections%’;
+—————–+——-+
| Variable_name | Value |
+—————–+——-+
| max_connections | 1000 |
+—————–+——-+
可以在/etc/my.cnf里面設(shè)置數(shù)據(jù)庫的最大連接數(shù)
[mysqld]
max_connections = 1000
max_connections 參數(shù)可以用于控制數(shù)據(jù)庫的最大連接數(shù):
3.mysql> show variables like ‘%connect%’;
+————————–+——————-+
| Variable_name | Value |
+————————–+——————-+
| character_set_connection | latin1 |
| collation_connection | latin1_swedish_ci |
| connect_timeout | 10 |
| init_connect | |
| max_connect_errors | 10 |
| max_connections | 4000 |
| max_user_connections | 0 |
+————————–+——————-+
Too many connections
很多開發(fā)人員都會遇見”MySQL: ERROR 1040: Too many connections”的異常情況,造成這種情況
原因是訪問量過高,MySQL服務(wù)器抗不住,這個時候就要考慮增加從服務(wù)器分散讀壓力;
另一種原因就是MySQL配置文件中max_connections值過小。
首先,我們來查看mysql的最大連接數(shù):
mysql> show variables like ‘%max_connections%’;
+—————–+——-+
| Variable_name | Value |
+—————–+——-+
| max_connections | 151 |
+—————–+——-+
1 row in set (0.00 sec)
其次,查看服務(wù)器響應(yīng)的最大連接數(shù):
mysql> show global status like ‘Max_used_connections’;
+———————-+——-+
| Variable_name | Value |
+———————-+——-+
| Max_used_connections | 2 |
+———————-+——-+
1 row in set (0.00 sec)
可以看到服務(wù)器響應(yīng)的最大連接數(shù)為2,遠遠低于mysql服務(wù)器允許的最大連接數(shù)值。
對于mysql服務(wù)器最大連接數(shù)值的設(shè)置范圍比較理想的是:服務(wù)器響應(yīng)的最大連接數(shù)值占服務(wù)器上限連接數(shù)值的比例值在10%以上,如果在10%以下,說明mysql服務(wù)器最大連接上限值設(shè)置過高。
Max_used_connections / max_connections * 100% = 2/151 *100% ≈ 1%
我們可以看到占比遠低于10%(因為這是本地測試服務(wù)器,結(jié)果值沒有太大的參考意義,大家可以根據(jù)實際情況設(shè)置連接數(shù)的上限值)。
再來看一下自己 linode VPS 現(xiàn)在(時間:2013-11-13 23:40:11)的結(jié)果值:
mysql> show variables like ‘%max_connections%’;
+—————–+——-+
| Variable_name | Value |
+—————–+——-+
| max_connections | 151 |
+—————–+——-+
1 row in set (0.19 sec)
mysql> show global status like ‘Max_used_connections’;
+———————-+——-+
| Variable_name | Value |
+———————-+——-+
| Max_used_connections | 44 |
+———————-+——-+
1 row in set (0.17 sec)
這里的最大連接數(shù)占上限連接數(shù)的30%左右。
上面我們知道怎么查看mysql服務(wù)器的最大連接數(shù)值,并且知道了如何判斷該值是否合理,下面我們就來介紹一下如何設(shè)置這個最大連接數(shù)值。
方法1:
mysql> set GLOBAL max_connections=256;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like ‘%max_connections%’;
+—————–+——-+
| Variable_name | Value |
+—————–+——-+
| max_connections | 256 |
+—————–+——-+
1 row in set (0.00 sec)
方法2:
修改mysql配置文件my.cnf,在[mysqld]段中添加或修改max_connections值:
max_connections=128
重啟mysql服務(wù)即可。
既然不是數(shù)據(jù)庫導致的,通過性能日志也可以確認不是代碼中有死循環(huán)或者數(shù)據(jù)庫調(diào)用次數(shù)過多的問題,我們就思考是否為JVM層面的問題。在登錄線上機器之后,我們使用首先使用top命令查看了該機器進程的運行情況:
查看cpu使用率,找到cpu 大于100%以上的進程id,進一步查看是具體的哪一個線程運行的cpu如此之高:
top -Hp 2580
結(jié)果看到id為2598 的線程運行cpu達到了97%,基本上可以確定是這個線程的運行導致項目整體運行較慢。接下來我們使用jstack命令查看了該進行各個線程運行情況,具體的命令如下:
jstack 2580 >/jstack.log
這里有兩點需要注意:
jstack命令需要再jdk的bin目錄下執(zhí)行,并且必須要以當前啟動項目tomcat的用戶身份運行,如果不是該用戶登錄的,可以使用如下命令導出線程運行日志:
sudo -u admin ~/jdk/bin/jstack 2580 >/jstack.log
看到有大量的GC操作,導致的緩慢,進一步我們使用:
jstat 命令查看內(nèi)存使用情況:
jstat -gcutil 2580 1000 5
接下來查看
內(nèi)存的使用情況
jmap -histo 2580,可以看到,創(chuàng)建的數(shù)量比較高,創(chuàng)建頻率比較快導致JVM進行了大量的gc工作,最終導致工程性能降低.
---------------------
作者:qq_40046779
來源:CSDN
原文:https://blog.csdn.net/qq_40046779/article/details/85157559