こんにちは。生産プラットフォーム開発部の中嶋です。生産プラットフォーム開発部はアパレル生産のDXを進めている部門です。具体的には服作りのIT化を含めたアパレル生産の効率化の促進と「生産支援」のシステムを主にGoで開発しています。今回はその運用の中でGoプログラムの実行時間をどのように短縮したのかを紹介します。
学べること・解決できること
- Goのメモリエラーに対するアプローチ例
- Go視点からみるメモリの基本的な知識
- チャネルの基本について
- ゴルーチンの具体的な実装例
- 時間がかかる重い処理の分析とGoを用いた最適化
背景
生産プラットフォームのバックエンドシステムは、複数のクラウドや自社・他社システムと連携をしながら製品に関する生産データを収集・デジタル化しています。例えば生産工程の進捗や検品データを収集してシステムに定期的に取り込みを行うなどです。
主にデータ連携はdigdagを利用し定期的に行っています。タスク自体はGoで開発し、各連携タスクは30分以内で終了することをシステム要件としています。
エラー発生
その連携タスクの1つが30分で完了しなくなり、タイムアウト時間を60分、さらに120分まで延長して問題を先送りしていました。それがある日を境に以下のようなエラーが発生しはじめます。いわゆるOOM(out of memory)です。
docker: Error response from daemon: failed to create shim: OCI runtime create failed: container_linux.go:380:
starting container process caused: process_linux.go:545: container init caused:
Running hook #0:: error running hook: exit status 2, stdout: , stderr: fatal error:
out of memory allocating heap arena map
調査・対応
まずはSREチームとインフラ面での調査・対応を試みました。
エラーの発生するタイミングのプロセス数が一気に上がっており、その影響で処理が追いつかなくなっているようでした。エラーが発生した当日に運用作業で新たにデータ登録作業がありました。そのデータは該当タスクの対象母数となるものです。
エラーの一因としてUbuntu18で起動時のメモリ消費量が増加している影響がありそうでした。Increase in memory consumption after updating Ubuntu to 18.04LTS
インスタンスの変更
リソース不足が原因であると仮説を立て、冗長化と世代を上げる対応でスケールアップを試みました。
処理自体が動くようdigdagエージェントのインスタンス数のスケールアップを行いました。問題発生前まではインスタンスが1だったのを最大4まで増加させました。一時的にエラーは止まりますが、複数タスクが起動する時間帯によっては同じエラーが発生していました。
今回問題が発生したインスタンスタイプはt2.mediumです。入れ替えたインスタンスはt3.medium、そしてm5.largeとスケールアップを試みました。下図にあるようにt2.mediumとt3.mediumはOSのメモリサイズは同値のため効果はありませんでした。
続きはこちら