Techioz Blog

Ruby AWS SDK を使用してスレッドで同期 Lambda を呼び出す場合の NetTimeout

概要

これには私は本当に困惑しており、誰かがこれについて何らかの洞察を持っていることを願っています。 Ruby と AWS SDK を使用して AWS Lambda を同期的に呼び出します。 Lambda が完了するまでにかかる時間は「通常」 7 分以内です。

AWS コンソールで Lambda に定義されているタイムアウトは 600 秒 (10 分) です。 AWS Lambda クライアント オブジェクトの構成は次のとおりです。

{
  http_read_timeout: 600,
  max_attempts: 1,
  retry_limit: 0
}

この Lambda をスレッド内で複数回呼び出す必要があるという要件があります。各スレッドは、異なる AWS Lambda クライアント オブジェクト (ただし、上記の構成は同じ) を使用し、呼び出し時にそれに渡される異なるイベント ペイロードを使用します。私たちのプログラムは、呼び出しを行っているすべてのスレッドが完了するまで待機します。

ローカルでは、コンピューターからは非常に確実に動作します。ただし、プログラムが ECS 内で実行されると、NET::Timeout TCP ソケット エラーが発生します。 Lambda は X 回呼び出します。 Lambda 内のコードは成功します。しかし、呼び出しを実行しているスレッド内の AWS Lambda クライアントは、Lambda からの応答を受信せずに 600 タイムアウトに達し、NET::Timeout TCP エラーで失敗します。

次のように設計を変更できます。

しかし、それは簡単な再設計やリファクタリングではありません。おそらく 6 日間の開発/テスト作業が必要ですが、私たちにはそのような作業はありません。

しかし、この問題に関して貴重な洞察を持っている人には感謝したいと思います。対話をしてアイデアを共有しましょう。

親切な皆さん、ありがとう!

解決策

これは解決できたと思います。誰かが同じような問題を抱えている場合、これが彼らを助けることを願っています。

問題はクライアント側にありました。具体的には、alpine docker コンテナ OS です。する必要がありました

a)。 tcp_keepalive_time = 300 を設定します。

https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html

b)。 tcp_syn_retries = 8 に設定します。

https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https://man7.org/linux/man-pages/man7/tcp.7.html http://willbryant.net/overriding_the_default_linux_kernel_20_second_tcp_socket_connect_timeout

ECS コンテナ内のプログラムが AWS Lambda API に API 呼び出しを正常に送信していることがわかりました。 Lambda API がそれを受け取り、Lambda をトリガーしました。しかし、クライアント側 (ECS コンテナ) のソケットが閉じられていました。しかし、私たちのアプリはこれをまったく認識していませんでした。

また、AWS Linux 上の RestClient / Net::HTTP での connect(2) タイムアウトの増加で説明されているように、Net::HTTP にモンキーパッチを適用する必要がありました。