Kürzlich habe ich bei einer kleineren Web Applikation das Upload Frontend auf Plupload umgestellt und die maximale Dateigröße auf 2 GB erhöht. Dabei habe ich auch auch eine chunk-size von 16MB für alle Uploads eingeführt, welche bei allen HTML5 fähigen Browsern automatisch aktiv ist (dazu zählt nicht der IE9, der noch in vielen Firmen verbreitet ist). Das Zusammenspiel zwischen ModSecurity, großen Dateien und den daraus resultierenden zeitlichen Limits ist böse, finde ich  😉

Das Problem

Upload 2 GB → Apache Reverse Proxy ModSec (SLES 11) → Backend Apache (Debian 7) = Abbruch.

Das Problem bei ModSec ist ja, dass es den kompletten Upload erst einmal cached um ihn zu scannen. ModSec erlaubt also nicht, den 2 GB Upload in 16 MB Häppchen an das Backend weiter zu schieben sondern wartet brav bis die vollständigen 2 GB empfangen worden sind. Man kann sich vorstellen, dass der Upload von 2 Gigabyte über eine langsame Internet Leitung eine Weile dauern kann. Der zweite Upload, von Proxy ans Backend, geschieht dann sehr schnell mit über 500MB/s im internen Netz. Doch genau hier erfolgte immer öfters Verbindungsabbruch, denn, das Backend hat die initial erstellte «pooled connection» längst wieder geschlossen.

  • User 1 macht einen Upload. Proxy > Backend erstellt eine Initial Connection. Proxy ModSec cached bis zu 2 GB , bevor er den Upload in einem Rutsch nach hinten schiebt.
  • User 2 macht auch einen Upload. Proxy > Backend erstellt eine Initial Connection, über die „shared“ offene, aber unbenutzte Session von User 1.
  • User 1 ist fertig mit dem Upload. Proxy schiebt den Content ans Backend. Backend schickt bei Ende einen Connection Reset an den Proxy
  • User 2’s Upload ist jetzt auch fertig. Proxy versucht es in einem Rutsch ans Backend zu schieben über die Initial-Pooled Session von vorhin – die ist aber geschlossen, weil User 1’s Upload schon fertig war – der Upload wird verworfen.

So, oder so ungefähr interpretiere ich die Situation.

Die Lösung

Deaktivieren der «pooled connection» ist hier die benötigte Wunderoption für mod_proxy:

proxy-initial-not-pooled=1

Die Apache Dokumentation schreibt hierzu:

If this variable is set no pooled connection will be reused if the client connection is an initial connection. This avoids the „proxy: error reading status line from remote server“ error message caused by the race condition that the backend server closed the pooled connection after the connection check by the proxy and before data sent by the proxy reached the backend. It has to be kept in mind that setting this variable downgrades performance, especially with HTTP/1.0 clients.

Ob Apache 2.2 oder 2.4 benutzt wird ist vermutlich irrelevant. Übrigens kann in der Praxis zu Testzwecken auch force-proxy-request-1.0=1 & proxy-nokeepalive=1 hinzugefügt werden, die angedeutete Performance Verschlechterung dürfte kaum ins Gewicht fallen.

PS: Oh, nein nein, ich bin kein Proxy Spezialist und möchte es auch nie werden 😉


Schroeffu

Der Autor ist Schweizer, verheiratet, Vater von bisher einem Kind und seit November 2015 zu seiner liebevollen Frau nach Braunschweig, Deutschland, ausgewandert. Mit im Gepäck: Die Familienplanung, jede Menge Plüsch-Pinguine und die Tastatur zum bloggen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.