程序運行一段時間后,總是出現(xiàn)大量的buys。
直接上代碼:
strace -ttp 13190
strace: Process 13190 attached
23:13:34.562338 restart_syscall(<... resuming interrupted read ...>) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
23:13:53.306786 --- SIGALRM {si_signo=SIGALRM, si_code=SI_USER, si_pid=3990, si_uid=0} ---
23:13:53.306876 rt_sigreturn({mask=[]}) = -1 EINTR (Interrupted system call)
23:13:53.307042 poll([{fd=31, events=POLLIN|POLLERR|POLLHUP}], 1, 86400000) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
php 13190 root 29u IPv4 337856578 0t0 TCP 127.0.0.1:43928->127.0.0.1:2016 (ESTABLISHED)
php 13190 root 30u IPv4 338776580 0t0 TCP 127.0.0.1:42530->127.0.0.1:63794 (ESTABLISHED)
php 13190 root 31u IPv4 339256252 0t0 TCP 10.88.88.16:39998->10.88.88.10:4936 (ESTABLISHED)
php 13190 root 32u IPv4 339279700 0t0 TCP 10.88.88.16:50944->10.88.88.10:4936 (ESTABLISHED)
php 13190 root 34u REG 253,1 9216 923360 /etc/pki/nssdb/cert9.db
php 13190 root 35u REG 253,1 11264 923362 /etc/pki/nssdb/key4.db
其中 10.88.88.10 是數(shù)據(jù)庫。
求賜教
卡在數(shù)據(jù)庫,可能是有慢sql,也可能是連數(shù)據(jù)庫超時
ttp 后返回的大概是
poll([{fd=9, events=POLLIN|POLLERR|POLLHUP}], 1, 0) = 1 ([{fd=9, revents=POLLIN}])
accept(9, {sa_family=AF_INET, sin_port=htons(50748), sin_addr=inet_addr("127.0.0.1")}, [128->16]) = 51
fcntl(51, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(51, F_SETFL, O_RDWR|O_NONBLOCK) = 0
epoll_ctl(6, EPOLL_CTL_ADD, 51, {EPOLLIN, {u32=51, u64=51}}) = 0
epoll_wait(6, [{EPOLLIN, {u32=51, u64=51}}], 32, 3280) = 1
recvfrom(51, "\0\0\0'\17\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\0\0\v1788"..., 65535, 0, NULL, NULL) = 39
sendto(51, "\0\0\0\6a:0:{}", 10, 0, NULL, 0) = 10
epoll_wait(6, [{EPOLLIN, {u32=51, u64=51}}], 32, 3279) = 1
recvfrom(51, "", 65535, 0, NULL, NULL) = 0
epoll_ctl(6, EPOLL_CTL_DEL, 51, 0x7ffec4aa5f70) = 0
close(51) = 0
epoll_wait(6, [{EPOLLIN, {u32=9, u64=9}}], 32, 3279) = 1
poll([{fd=9, events=POLLIN|POLLERR|POLLHUP}], 1, 0) = 1 ([{fd=9, revents=POLLIN}])
accept(9, {sa_family=AF_INET, sin_port=htons(50796), sin_addr=inet_addr("127.0.0.1")}, [128->16]) = 51
fcntl(51, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(51, F_SETFL, O_RDWR|O_NONBLOCK) = 0
epoll_ctl(6, EPOLL_CTL_ADD, 51, {EPOLLIN, {u32=51, u64=51}}) = 0
epoll_wait(6, [{EPOLLIN, {u32=51, u64=51}}], 32, 2808) = 1
recvfrom(51, "\0\0\1\t\16\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\0\0\17[\"17"..., 65535, 0, NULL, NULL) = 265
epoll_wait(6, [{EPOLLIN, {u32=51, u64=51}}], 32, 2807) = 1
recvfrom(51, "", 65535, 0, NULL, NULL) = 0
epoll_ctl(6, EPOLL_CTL_DEL, 51, 0x7ffec4aa5f70) = 0
close(51) = 0
我好像看到了redis 返回了 +OK, 這個有辦法確認是哪行語句嗎?我所有的redis都是在子進程實例化的
14:20:49.652824 recvfrom(30, "+OK\r\n", 8192, MSG_DONTWAIT, NULL, NULL) = 5
有可能和這個SQL有關(guān)系,SELECT account,name,`im"... , 完整sql沒打印出來。
看起來是數(shù)據(jù)庫一直沒返回數(shù)據(jù),進程一直在等返回。
下次strace可以加個 -s500
的參數(shù),類似 strace -s500 -ttp 進程pid
這樣可以打印完整的參數(shù)包括sql語句出來
看起來確實和 SELECT account,name,imname,id,nickname,impassword,logo FROM touser_auth_user WHERE imname = ?
這個sql有一定關(guān)系,你可以嘗試下寫個腳本請求下數(shù)據(jù)庫看下是否有問題??聪聰?shù)據(jù)庫是否有有錯誤日志或者慢sql。
fd 32是數(shù)據(jù)庫,不是redis,那兩個寫操作看不出來是發(fā)送得什么數(shù)據(jù)給數(shù)據(jù)庫
大大,經(jīng)過調(diào)試,和打印sql,拿出sql比較和執(zhí)行,那些sql都是正常的,也是能返回數(shù)據(jù)的,最終跟蹤發(fā)現(xiàn),就是不定時,不定sql的會出現(xiàn)問題,卡住在那,原因不明。 有沒有什么語句可以監(jiān)控到busy,或者進程長時間busy時讓這個進程重啟的方法?
每個進程設(shè)置個定時器,定時向磁盤寫入當前時間戳到一個自己pid命名的文件。另外啟動一個進程,這個進程讀取磁盤上所有的pid文件里的時間戳,如果時間戳超過一定時間沒更新,認為這個pidbusy,然后執(zhí)行 posix_kill($pid, SiGKILL);殺死進程。
另外嘗試給pdo加個超時,應(yīng)該是在php.ini中設(shè)置,找下資料,比如讀數(shù)據(jù)超過1秒就返回失敗,這樣就不會卡幾分鐘這種。
這個問題有可能是php的bug,不要用小版本太新的php版本。另外也有可能是硬件網(wǎng)卡丟包導(dǎo)致,也可能是mysql服務(wù)端linux內(nèi)核配置有問題,甚至也有可能是防火墻問題。參考這里http://wtbis.cn/doc/workerman/appendices/kernel-optimization.html 嘗試優(yōu)化下linux內(nèi)核包括mysql服務(wù)端。
數(shù)據(jù)庫用的是阿里的PolarDB ,找到對應(yīng)的時間和sql看了下,返回都是0.0x毫秒的返回。 pdo的話,一開始我覺的可能是tp的 orm有問題,因為用到了多庫,出現(xiàn)問題的大部分是第二個庫,然后就部分改造為了使用workerman/mysql,但事實發(fā)現(xiàn),其實第一個庫也會,使用workerman/mysql的也會, 硬件的話,使用的是阿里的ecs, 我也長時間ping過,未發(fā)現(xiàn)丟包,而且都是0.x毫秒級別的響應(yīng)。 linux內(nèi)容優(yōu)化是按照上面這個教程優(yōu)化的。 唯一還能定義的,可能就php版本問題? 目前使用的是 v7.3.33, 不知道是不是這個。 之前我用8.0 進程斷的更離譜,然后降下版本來的
阿里的DB好像連接超過1分鐘就會被斷開,并且不帶fin通知的那種,導(dǎo)致客戶端傻等。在onWorkerStart里嘗試加個定時器,定時select 1,保持連接試下。定時間隔先設(shè)置為25秒。
select 1后,我配合2小時自動重啟一次,好像昨晚到現(xiàn)在是正常的了,如果是這樣的話,那么的確很有可能是阿里的DB不帶fin通知的那種斷開,說到這個,雖然無法確認是否1分鐘,但通過排查這個業(yè)務(wù)來看的話,最長不超過300s,正常里面的業(yè)務(wù)是 300s緩存在redis,過期才去重新取db,所以很可能的確是這里問題了。有新問題我再反饋。謝謝walkor大大