問題
前段時間,開發同事反應出應用程序在insert數據時出現
[com.eyou.reyun.controller.reyun.ReyunAndroidGameLogController%addGameLoginLog() 161 ] - Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.GetConnectionTime outException: wait millis 10000, active 56, maxActive 800, creating 1, createElapseMillis 28926
分析
連接數據庫異常。 查看當時的客戶端接數也達到800+; 這個不正常。初步考慮是不是數據庫被入侵;根據監聽日志;去查看當天的連接情況。
awk -F"=" '/CONNECT_DATA/{print $10}' log.xml | awk -F')' '{a[$1]++}END{for(i in a)print i,a[i]}'
連接數據庫都是應用程序的服務器; 有各個媒體的數據、自有SDK數據、以及服務器本地。 其中自有SDK所在的服務器有大量的連接。超過70%。
初步診斷是連接數不夠;導致應用程序大量重復申請連接,數據庫支撐不了這么大數據量;
- 單機Oracle數據庫(主備模式)、未采用讀寫分離
- 主庫有大量定時任務
- 配置相對比較差。服務器的CPU配置
vendor_id : GenuineIntel cpu family : 6 model : 62 model name : Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz stepping : 4 cpu MHz : 2100.170 cache size : 15360 KB physical id : 0 siblings : 12 cpu cores : 6 cpuid level : 13
解決
先從數據庫分析解決
1、增加連接數
目前Oracle數據庫的最大連接數是1000;相對足夠大了。因為Oracle是進程數據庫;不像mysql那樣能支持大量的客服端連接不像mysql那樣能支持大量的客服端連接
在這需要吐槽下Oracle;連個連接池的中間件也找不到;是不是繳費了才有這服務。
2、解除限制非活躍回話
為啥應用程序會大量重復連接數據庫呢?是限制非活躍回話超過多少分鍾就自動斷開
alter system set resource_file=FALSE;
3、取消外網監聽、以及服務器上網
做了上面3步;上面ConnectionTimeoutException;沒有出現;但是出現
socket() failed (24: Too many open files) while connecting to upstream
若單獨百度查詢;這個可能不管數據庫的事;但是連接數還是沒有降下來
4、查看哪些應用數據是否可以取消錄入
核查后;發現有個游戲登錄記錄是CP方通過接口傳遞過來的;游戲登錄數據自有SDK也是有的;只是沒有角色信息。而推廣平台未涉及到角色的層次的統計。
通過以上處理;在寫個腳本監控下連接數
#!/bin/sh n=`ps -ef|grep oracleorcl | grep "LOCAL=NO" |wc -l` d=`date` echo "$d:$n" >> /home/oracle/log/oracle_p_num if [ $n -gt 900 ];then echo $n >> /home/oracle/killorcl.log ps -ef|grep oracleorcl | grep "LOCAL=NO" |awk '{system("kill -9 " $2)}' echo "$d" >> /home/oracle/killorcl.log fi
在 oracle_p_num 記錄每分鍾的統計; 觀察下一周數據庫連接數趨於平穩100左右;oracle晚上10點會做統計信息收集;最高不超過150的連接數。
拓展
最后:考慮后期公司游戲業務發展/上線;需重新規划下數據庫架構;重新挑選下數據庫服務器;將Oracle遷移到PostgreSQL12。采用讀寫分離模式(邏輯復制+hot standby+pgbouncer)
最近通過編寫PostgreSQL存儲過程有些心得;后期可考慮寫一系列的PostgreSQL的存儲過程教程。