n1sym tech blog

Rails の ajax 処理で504エラーが出たので対処した

以下のエラーが消えずに困っていた。

rails-ujs.js:216 POST https://*** 504

どうもリクエストから60秒経つと強制でタイムアウトとなるのが原因っぽい。

処理の流れは以下のような感じ。どこでタイムアウトが発生しているのか調べてみる。

Internet => ALB => ECS => Nginx => Puma => Rails => ajax

ajax

ajax処理の中身は XMLHttpRequest。ドキュメントを見てみる。デフォルト設定ではタイムアウトは無かった。

XMLHttpRequest.timeout は unsigned long 型で、リクエストが自動的に終了するまでの時間をミリ秒で示します。既定値は 0 で、タイムアウトが無いことを示します。

XMLHttpRequest.timeout - Web API | MDN

Rails + Puma

ソースは見つからなかったが、Rails と Puma にはタイムアウトの制御は無いらしい。

Railsでタイムアウトのエラーをログに出力する方法 - Qiita

Nginx

第一の原因は Nginx だった。とりあえず以下のようにタイムアウト時間を 60秒 => 180秒 に設定。

  sendfile        on;
  keepalive_timeout  180;
  send_timeout 180;
  proxy_connect_timeout 180;
  proxy_read_timeout    180;
  proxy_send_timeout    180;

  upstream app {
    server unix:///app/tmp/sockets/puma.sock;
  }

ALB

Nginx の修正だけでは直らなかったのでALBまで遡った。

    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      IpAddressType: ipv4
      LoadBalancerAttributes:
        - Key: idle_timeout.timeout_seconds
          Value: 180

AWS::ElasticLoadBalancingV2::LoadBalancer - AWS CloudFormation

これで解決した。

← Back to home