有個常駐進程 監(jiān)聽rabbitmq隊列,如果這個隊列有信息進來就把這個信息保存到一個數(shù)據(jù)庫表中,自打上線后發(fā)現(xiàn)個規(guī)律只能運行一小段兒時間正常,過一段時間后就無法保存數(shù)據(jù)庫了,日志報異常
SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
應(yīng)該是數(shù)據(jù)庫連接丟失了,理論上model應(yīng)該有自動重連的機制,這個需要特殊配置嗎?還是說有其他解決方案?
Model::create(['id'=>'123']); // 主要就這樣保存的
SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
"workerman/webman-framework": "~2.1",
"workerman/workerman": "~5.1",
崗?fù)ね綌?shù)據(jù)業(yè)務(wù)數(shù)據(jù)處理異常 {"message":"SQLSTATE[HY000]: General error: 2006 MySQL server has gone away (Connection: mysql, SQL: select * from `vehicle_passage_tickets` where `is_entry` = 1 and `status` <> void and (`available_start_datetime` between 2025-02-13 00:00:00 and 2025-02-13 23:59:59 or `available_end_datetime` between 2025-02-13 00:00:00 and 2025-02-13 23:59:59 or (`available_start_datetime` <= 2025-02-13 00:00:00 and `available_end_datetime` >= 2025-02-13 23:59:59 and `status` = pending_use)))","trace":"#0 /var/www/backend-service/vendor/illuminate/database/Connection.php(979): Illuminate\\Database\\Connection->runQueryCallback()
#1 /var/www/backend-service/vendor/illuminate/database/Connection.php(958): Illuminate\\Database\\Connection->tryAgainIfCausedByLostConnection()
#2 /var/www/backend-service/vendor/illuminate/database/Connection.php(781): Illuminate\\Database\\Connection->handleQueryException()
#3 /var/www/backend-service/vendor/illuminate/database/Connection.php(398): Illuminate\\Database\\Connection->run()
#4 /var/www/backend-service/vendor/illuminate/database/Query/Builder.php(3133): Illuminate\\Database\\Connection->select()
#5 /var/www/backend-service/vendor/illuminate/database/Query/Builder.php(3118): Illuminate\\Database\\Query\\Builder->runSelect()
#6 /var/www/backend-service/vendor/illuminate/database/Query/Builder.php(3706): Illuminate\\Database\\Query\\Builder->Illuminate\\Database\\Query\\{closure}()
#7 /var/www/backend-service/vendor/illuminate/database/Query/Builder.php(3117): Illuminate\\Database\\Query\\Builder->onceWithColumns()
#8 /var/www/backend-service/app/service/TollGateSyncDataService.php(97): Illuminate\\Database\\Query\\Builder->get()
#9 /var/www/backend-service/app/service/TollGateSyncDataService.php(47): app\\service\\TollGateSyncDataService->getAvailableTickets()
#10 /var/www/backend-service/app/process/TollGateDataMonitor.php(202): app\\service\\TollGateSyncDataService->getAvailableTollGateData()
#11 /var/www/backend-service/app/process/TollGateDataMonitor.php(170): app\\process\\TollGateDataMonitor->downloadTollGateData()
#12 /var/www/backend-service/app/process/TollGateDataMonitor.php(77): app\\process\\TollGateDataMonitor->processMessage()
#13 [internal function]: app\\process\\TollGateDataMonitor->app\\process\\{closure}()
#14 /var/www/backend-service/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Channel/AMQPChannel.php(1063): call_user_func()
#15 [internal function]: PhpAmqpLib\\Channel\\AMQPChannel->basic_deliver()
#16 /var/www/backend-service/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Channel/AbstractChannel.php(221): call_user_func()
#17 /var/www/backend-service/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Channel/AbstractChannel.php(367): PhpAmqpLib\\Channel\\AbstractChannel->dispatch()
#18 /var/www/backend-service/app/process/TollGateDataMonitor.php(130): PhpAmqpLib\\Channel\\AbstractChannel->wait()
#19 /var/www/backend-service/app/process/TollGateDataMonitor.php(59): app\\process\\TollGateDataMonitor->startMonitor()
#20 /var/www/backend-service/vendor/workerman/webman-framework/src/support/helpers.php(512): app\\process\\TollGateDataMonitor->onWorkerStart()
#21 /var/www/backend-service/vendor/workerman/webman-framework/src/support/helpers.php(558): worker_bind()
#22 /var/www/backend-service/vendor/workerman/workerman/src/Worker.php(2571): {closure}()
#23 [internal function]: Workerman\\Worker->Workerman\\{closure}()
#24 /var/www/backend-service/vendor/workerman/workerman/src/Worker.php(2586): Fiber->start()
#25 /var/www/backend-service/vendor/workerman/workerman/src/Worker.php(1740): Workerman\\Worker->run()
#26 /var/www/backend-service/vendor/workerman/workerman/src/Worker.php(1544): Workerman\\Worker::forkOneWorkerForLinux()
#27 /var/www/backend-service/vendor/workerman/workerman/src/Worker.php(1524): Workerman\\Worker::forkWorkersForLinux()
#28 /var/www/backend-service/vendor/workerman/workerman/src/Worker.php(593): Workerman\\Worker::forkWorkers()
#29 /var/www/backend-service/vendor/workerman/webman-framework/src/support/App.php(143): Workerman\\Worker::runAll()
#30 /var/www/backend-service/start.php(5): support\\App::run()
#31 {main}","data":"{\"cmd\":\"get_toll_gate_all_data\",\"toll_gate_code\":\"1001\",\"sync_datetime\":\"2025-02-14 10:57:20\",\"id\":\"oxcs5vnp1r\"}"} []
回來報告一下消息:
按照walkor老大指引的開啟了協(xié)程的方式,數(shù)據(jù)庫開啟了連接池,經(jīng)過一晚的時間測試 還是沒能解決問題:
SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
配置如下:
return [
'default' => 'mysql',
'connections' => [
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST'),
'port' => env('DB_PORT'),
'database' => env('DB_NAME'),
'username' => env('DB_USER'),
'password' => env('DB_PASSWORD'),
'charset' => env('DB_CHARSET'),
'collation' => env('DB_COLLATION'),
'unix_socket' => '',
'prefix' => '',
'strict' => true,
'engine' => null,
'options' => [
PDO::ATTR_EMULATE_PREPARES => false,
],
'pool' => [ // 連接池配置,僅支持swoole/swow驅(qū)動
'max_connections' => (int)env('DB_POOL_MAX_CONNECTIONS'), // 最大連接數(shù)
'min_connections' => (int)env('DB_POOL_MIN_CONNECTIONS'), // 最小連接數(shù)
'wait_timeout' => 3, // 從連接池獲取連接等待的最大時間,超時后會拋出異常
'idle_timeout' => 180, // 連接池中連接最大空閑時間,超時后會關(guān)閉回收,直到連接數(shù)為min_connections
'heartbeat_interval' => 60, // 連接池心跳檢測時間,單位秒,不要小于60
],
],
],
];
監(jiān)聽的進程配置如下:
'test_pusher' => [
'handler' => TestPusher::class,
'count' => 1,
'eventLoop' => \Workerman\Events\Swoole::class,
],
回來再報個信息,更新后今天大部分都正常,但是收到一個錯誤:
PDO::prepare(): Send of 132 bytes failed with errno=110 Connection timed out (Connection: mysql, SQL: insert into push_test (push_url, request_data, push_times, id, updated_at,
回來再報問題,經(jīng)過這幾天的測試發(fā)現(xiàn)上面提到的問題還是依然存在,大概現(xiàn)象就是,這個進程大概1天半的時間沒有與數(shù)據(jù)庫通信是靜默狀態(tài)沒有數(shù)據(jù)推送過來,等到再次有數(shù)據(jù)推送過來的時候一定會報錯:
"error":"PDO::prepare(): Send of 132 bytes failed with errno=110 Connection timed out
如果接下來繼續(xù)有數(shù)據(jù)推送程序就正常處理,如果再次隔很久才有數(shù)據(jù)推送過來處理入庫還是如上的報錯。
Connection timed out 和 MySQL server has gone away 是不同的錯誤類型了。一個是發(fā)送數(shù)據(jù)超時,一個是連接斷開。
你們用的什么數(shù)據(jù)庫?云數(shù)據(jù)庫?
可能是你們系統(tǒng)有什么防火墻之類的把不活躍連接清理了,導(dǎo)致超時了。
剛看了下代碼,PhpAmqpLib的wait()有超時參數(shù),你們設(shè)置個超時,比如50秒。
超時后執(zhí)行個SQL,這樣和數(shù)據(jù)庫定時通訊下,維持下連接。
求問,經(jīng)過這幾天的測試,還是這個問題,這種 timeout能否有什么方法手動去連接數(shù)據(jù)庫呢?
PDO::prepare(): Send of 132 bytes failed with errno=110 Connection timed out
50秒通訊一次該如何實現(xiàn)呢? 因為理論上mq的進程是阻塞試的,一單這個進程啟動他就一直在 wait的狀態(tài)了,這個狀態(tài)下如何嘗試50秒與數(shù)據(jù)庫通訊一次?
另外我有個不明白的地方 理論上我啟用的swoole模式下的連接池配置,理論上連接池會有心跳維持,當(dāng)有數(shù)據(jù)庫操作的時候不會出現(xiàn)連接timeout的狀態(tài)因為連接池理論上是肯定有個min可用連接的,對吧?難道是連接池在這種自定義進程的模式下是不起作用的嗎?
50秒通訊一次就是上面說的利用wait()的超時參數(shù),超時后調(diào)用一次數(shù)據(jù)庫。
連接從連接池里獲取后沒歸還前不會調(diào)用心跳,連接沒歸還說明連接正在被使用,可能正在等待數(shù)據(jù),發(fā)出心跳查詢可能導(dǎo)致數(shù)據(jù)錯亂,swoole和swow下會報錯。