2013-08-08 11 views
7

Ich habe eine Rails (v3.2.13, Ruby 2.0.0) Anwendung läuft auf Nginx + Unicorn (Ubuntu 12.04). Alles funktioniert gut, außer wenn ein Admin-Benutzer Benutzer (Tausende) über eine CVS-Datei hochlädt. Das Problem ist, dass ich Timeout auf 30 Sekunden eingestellt habe und der Importvorgang viel mehr Zeit benötigt. Also, nach 30 Sekunden bekomme ich eine nginx 502 Bad Gateway Seite (Unicorn Arbeiter wird getötet).Wie konfiguriere ich nginx + Unicorn, um Timeout-Fehler zu vermeiden?

Die offensichtliche Lösung ist, Timeout zu erhöhen, aber ich will das nicht, weil es ein anderes Problem verursachen wird (ich denke), weil es kein typisches Verhalten ist.

Gibt es eine Möglichkeit, mit dieser Art von Problemen umzugehen?

Vielen Dank im Voraus.

PS: Vielleicht ist eine Lösung, den Code zu ändern. Wenn dem so ist, möchte ich vermeiden, dass der Benutzer eine andere Anfrage ausführt.

Einige Ideen (nicht wissen, wenn möglich):

  • -Setup ein Arbeiter auf diese Anforderung gewidmet ist.
  • Senden Sie ein "work in progress" -Signal an Unicorn, um zu vermeiden, getötet zu werden.

nginx-app.conf

upstream xxx { 
    server unix:/tmp/xxx.socket fail_timeout=0; 
} 


server { 
    listen 80; 

    ... 

    location/{ 

    proxy_pass http://xxx; 
    proxy_redirect  off; 
    ... 

    proxy_connect_timeout  360; 
    proxy_send_timeout   360; 
    proxy_read_timeout   360; 
    } 
} 

unicorn.rb

worker_processes 2 

listen "/tmp/xxx.socket" 

timeout 30 

pid "/tmp/unicorn.xxx.pid" 
+0

zu kurz PS, bitte länger machen. – juanpastas

+0

Danke @juanpastas, sehr hilfreich. – cortex

+2

Nur eine Anmerkung. Ihre Werte 'proxy_connect_timeout',' proxy_send_timeout', 'proxy_read_timeout' sind ungewöhnlich groß. Bitte lesen Sie die Dokumentation, Sie verstehen ihre Bedeutung wahrscheinlich nicht. Und 'fail_timeout = 0 'ist absolut bedeutungslos. – VBart

Antwort

9

Dies ist ein guter Grund, eine Warteschlange zu erstellen. Und werden Sie:

  • Upload CSV-Datei (das innerhalb 30sec sein sollte)
  • Ihre Hintergrundjobs, die Benutzerdaten importieren (das stundenlang gehen ...)
  • während dieser Job im Gange ist, dass Sie kann eine Art WIP-Seite mit Auftragsstatus/Prozenten/etc.

Überprüfen Sie zum Beispiel https://github.com/resque/resque. Es gibt viele andere Warteschlangen.

+0

Auf diese Weise können Sie viele Dinge tun ... wie das Senden von 1000 E-Mails, Konvertieren von Videos/Bildern ... Viele Dinge. – NilColor

+0

Ist Resque im Wesentlichen dasselbe wie Ruby Thread? Oder bin ich weit weg? http: //www.ruby-doc.org/core-2.1.1/Thread.html –

+0

Nein. Dies ist Message Queue (http://en.wikipedia.org/wiki/Message_queue). Resque selbst verwendet Threads, sicher. Thread ist für die parallele Verarbeitung. Warteschlange für asynchrone Verarbeitung. – NilColor

2

Gibt es eine Möglichkeit, diese Art von Problemen zu behandeln?

Machen Sie den Job im Hintergrund. Sie sollten über einen separaten Prozess verfügen, der Aufträge aus der Warteschlange einzeln abruft und verarbeitet. Und da es nicht mit Benutzeranforderungen funktioniert, kann es seine Arbeit so lange wie nötig erledigen. Sie brauchen dafür kein Einhorn, nur einen separaten Daemon.