【要約】自動売買BOTが再起動のたびに死ぬ — journalctlの7秒差にたどり着くまで [Zenn_Python] | Summary by TechDistill
> Source: Zenn_Python
Execute Primary Source
// Problem
開発者が運用する暗号資産自動売買BOTにおいて、再起動のたびに特定のBOTが「dead」判定され、スケジューラから除外される無限ループに直面した。調査の結果、以下の2点が課題として浮き彫りになった。
- ・メモリ制約のあるVM環境で、5分毎の強制GCがスワップを誘発し、GunicornのWorker Timeoutを引き起こしていた。
- ・復帰処理においてステータスのみを更新し、最終実行時刻(last_run_at)を更新していなかった。
- ・実行間隔が長いBOTほど、復帰直後に「実行間隔の閾値超過」と判定される競合が発生していた。
// Approach
開発者は、メモリ管理の最適化とスケジューラの復帰ロジックの修正という、二段階のアプローチを採用した。
- ・メモリ対策として導入していた
gc.collect()を削除し、CPythonの世代別自動収集に任せる運用へ変更した。 - ・復帰処理関数
revive_dead_bots()を実装し、ステータスの変更と同時にlast_run_atを現在時刻にリセットする処理を追加した。 - ・修正後、回帰テストにより実行間隔の短いBOTへの影響がないことを確認した。
// Result
開発者は、問題の修正と再発防止策の導入により、システムの安定稼働を実現した。
- ・特定のBOTが再起動のたびに停止する無限ループが解消された。
- ・GunicornのWorker Timeout連鎖が止まり、プロセス再起動の頻度が低下した。
- ・メモリ肥大化の予兆を捉えるため、ログレビューにRSSとスワップ使用量の観測項目を追加した。
Senior Engineer Insight
> リソース制約下でのPython運用において、GCとスワップの相互作用への理解は不可欠だ。また、分散システムやスケジューラを扱う際は、ステート(状態)の復旧において「属性の不整合」が致命的な競合を生むことを忘れてはならない。原因が完全特定できない段階で場当たり的な修正を避け、観測(Observability)を強化する判断は、実戦において極めて妥当である。