quatermain
quatermain

Reputation: 1452

Nginx + Unicorn do not allow upload file > 400mb

I have app in RoR, I test it on apache2 to upload file > 1 GB, it's working. But I must use nginx. I have this error after 100% upload on nginx server:

2012/11/09 17:17:01 [error] 1436#0: *12 upstream prematurely closed connection while reading response header from upstream, client: 134.19.136.32, server: my_domain, request: "POST /attachments HTTP/1.1", upstream: "http://unix:/tmp-sock/unicorn.my_domain.sock:/attachments", host: "my_domain", referrer: "http://my_domain/"

I think problem is with unicorn settings, but I don't know where exactly. BTW: Everthing work only in Firefox.

My config files:

#nginx main config
user www-data;
worker_processes 5;
pid /run/nginx.pid;

events {
    worker_connections 768;
    accept_mutex off;
    # multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # Logging Settings
    ##

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    ##
    # Gzip Settings
    ##

    gzip on;
    gzip_disable "msie6";

    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # nginx-naxsi config
    ##
    # Uncomment it if you installed nginx-naxsi
    ##

    #include /etc/nginx/naxsi_core.rules;

    ##
    # nginx-passenger config
    ##
    # Uncomment it if you installed nginx-passenger
    ##

    #passenger_root /usr;
    #passenger_ruby /usr/bin/ruby;

    ##
    # Virtual Host Configs
    ##
    output_buffers 1 2m;
    send_timeout 50s;
    client_body_temp_path /citishare/datastore0;
    client_max_body_size 204800m;
    reset_timedout_connection on;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

#site config
upstream unicorn {
  server unix:/tmp-sock/unicorn.citidrive.sock fail_timeout=10000;
}

server {
  listen 80 default deferred;
  server_name citidrive.citicom.sk;
  root /home/deployer/apps/citidrive/current/public;

  proxy_buffering on;
  proxy_buffer_size 8M;
  proxy_buffers 2048 8M;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  proxy_set_header   X-Accel-Mapping       /home/deployer/apps/citidrive/current/public/system/=/private_files/;
  proxy_set_header   X-Accel-Limit-Rate off;
  location /private_files/ {
          internal;
          alias   /home/deployer/apps/citidrive/current/public/system/;
      }
  try_files $uri/index.html $uri @unicorn;
    location @unicorn {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://unicorn;
        proxy_read_timeout 500;
      }
  error_page 500 502 503 504 /500.html;
  client_max_body_size 4G;
  proxy_max_temp_file_size 3072m;
  keepalive_timeout 80;
  client_header_timeout 3m;
  client_body_timeout 3m;
  send_timeout 3m;
}

#unicorn.rb
root = "/home/deployer/apps/citidrive/current"
working_directory root
pid "#{root}/tmp/pids/unicorn.pid"
stderr_path "#{root}/log/unicorn.log"
stdout_path "#{root}/log/unicorn.log"

listen "/tmp-sock/unicorn.citidrive.sock"
worker_processes 5
timeout 80

#unicorn_init.sh
#!/bin/sh
### BEGIN INIT INFO
# Provides:          unicorn
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Manage unicorn server
# Description:       Start, stop, restart unicorn server for a specific application.
### END INIT INFO
set -e

# Feel free to change any of the following variables for your app:
TIMEOUT=${TIMEOUT-60}
APP_ROOT=/home/deployer/apps/citidrive/current
PID=$APP_ROOT/tmp/pids/unicorn.pid
CMD="cd $APP_ROOT; bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E production"
AS_USER=deployer
set -u

OLD_PIN="$PID.oldbin"

sig () {
  test -s "$PID" && kill -$1 `cat $PID`
}

oldsig () {
  test -s $OLD_PIN && kill -$1 `cat $OLD_PIN`
}

run () {
  if [ "$(id -un)" = "$AS_USER" ]; then
    eval $1
  else
    su -c "$1" - $AS_USER
  fi
}

case "$1" in
start)
  sig 0 && echo >&2 "Already running" && exit 0
  run "$CMD"
  ;;
stop)
  sig QUIT && exit 0
  echo >&2 "Not running"
  ;;
force-stop)
  sig TERM && exit 0
  echo >&2 "Not running"
  ;;
restart|reload)
  sig HUP && echo reloaded OK && exit 0
  echo >&2 "Couldn't reload, starting '$CMD' instead"
  run "$CMD"
  ;;
upgrade)
  if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
  then
    n=$TIMEOUT
    while test -s $OLD_PIN && test $n -ge 0
    do
      printf '.' && sleep 1 && n=$(( $n - 1 ))
    done
    echo

    if test $n -lt 0 && test -s $OLD_PIN
    then
      echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds"
      exit 1
    fi
    exit 0
  fi
  echo >&2 "Couldn't upgrade, starting '$CMD' instead"
  run "$CMD"
  ;;
reopen-logs)
  sig USR1
  ;;
*)
  echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
  exit 1
  ;;
esac

Upvotes: 2

Views: 2522

Answers (2)

Aref Aslani
Aref Aslani

Reputation: 1636

Sending a huge file straight to your rails application is not a good solution for uploading big files. You can use nginx upload module to handle big file uploads using unicorn+nginx. This way, nginx actually handles the file upload and instead of passing the whole file to rails as multipart-form data, you send the local file path, uploaded by nginx, to the unicorn rails server and all rails does is to move the file from the tmp path of the os to the path you define. Here I configured nginx and rails to do upload job with nginx upload module. Now there are better solution for handling uploads such as TUS protocol.

Upvotes: 1

Aref Aslani
Aref Aslani

Reputation: 1636

I solved the problem by increasing the keepalive_timeout in the Nginx configuration. Maybe this is not a proper solution, or maybe you can increase that based on location and request type. And for that Firefox part, Firefox waits for a response longer than Chrome.

Upvotes: 0

Related Questions