概要
aws上でgoのフロントサーバとSQSで、サービスを展開していたのですが、その時にハマった体験談を書きたいと思います。
構成図
端末からリクエストをフロントサーバが受けてSQSに書き込み、バックエンドサーバがSQSから取り出して処理をするだけのシンプルな構成です。
サーバ(EC2)は随時autoscaleしています。

ハマった所
インスタンスが起動する時に、SQSへの接続に失敗して書き込みが出来ない事が度々あり、その間のリクエストがロストしてしまいました。
NW的な問題かとも思いましたが、調査が難しくアプリケーション側で対応を入れることにしました。
アプリケーション側の問題点
aws-sdk-goでは、クライアント作成時には接続に行かず、メッセージを送信する時に、接続がなければ接続に行く実装になっているため、実際に送信してみないと接続できるのかが分からないためでした。
参考までにコード
クライアント生成
// クライアント生成時にerrorを返さない
func New(p client.ConfigProvider, cfgs ...*aws.Config) *SQS {
c := p.ClientConfig(EndpointsID, cfgs...)
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName)
}
書き込み
// こちらはerrorを返す
func (c *SQS) SendMessage(input *SendMessageInput) (*SendMessageOutput, error) {
req, out := c.SendMessageRequest(input)
return out, req.Send()
}
解決方法
無理矢理ですが、クライアント生成直後にテスト用メッセージをSQSに送信して、失敗した場合は、ELBに入れない仕組みを実装しました。
もちろん、バックエンドサーバ側でテスト用のメッセージを捨てる実装も入れました。
もっといい方法を知っている方がいらっしゃいましたら教えて下さい・・・・。
最後に
SQS等のサービスは、すごく便利な反面、問題が起きた場合に調査が難しいため、アプリケーション側で上手く実装することが重要だと実感しました。