Verarbeiten von *grossen* HTTP-uploads

19/10/2007 - 23:35 von Ulli Horlacher | Report spam
Ich muss *richtig* *GROSSE* HTTP-uploads verarbeiten. Das kann bis in den
TB-Bereich gehen.

Der Apache (2.0) streikt schon bei laecherlichen 2 GB, also habe ich
selber einen Mini-Webserver (cgilaunch) geschrieben, der im Wesentlichen
nur CGIs startet mit exec($cgi). Meine CGI-Scripte benutzen das Perl
CGI-Modul.

Bei HTTP GET funktioniert das auch einwandfrei, nur bei HTTP POST haengen
sich die cgis auf. Ich hab das Problem dann lokalisiert: CGI.pm wertet
leider CONTENT_LENGTH nicht aus, sondern liest bis EOF. Das kommt aber
nicht, der Client haelt die Verbindung offen.

Mein Workaround ist nun, dass mein cgilaunch die Daten vom Client liest
und sie via pipe an das cgi-script weiterreichen und nach CONTENT_LENGTH
Bytes die Pipe schliesst (*). Dann bekommt CGI.pm sein EOF und alles
funktioniert.

Leider ist das im GB-Bereich nicht grad effizient. Im top sehe ich, dass
cgilaunch und das cgi-script sich um die CPU pruegeln. Beide sind so bei
knapp 50%.

Es waere also viel besser, wenn das CGI.pm seine Daten direkt vom
Netzwerk-Socket lesen koennte und dabei CONTENT_LENGTH beachten wuerde.
Notfalls patche ich das CGI.pm. Allerdings ist der Code da drin nicht ganz
trivial und ich weiss nicht wo und wie ich das Einlesen entsprechend
modifizieren kann.



(*) Code-Schnipsel dazu:

if ($cl = $ENV{CONTENT_LENGTH}) {
if (open P,"|$cgi") {
nvt_print("HTTP/1.1 200 OK");
nvt_print("Server: cgilaunch");
$rb = 0;
$bs = 512;
while ($rb<$cl) {
$b=$cl-$rb;
$b=$bs if $b>$bs;
if ($n = read(STDIN,$_,$b)) {
$rb += $n;
print P;
} else {
last;
}
}
close P;
wait;
exit;
} else {
http_error(406);
}
} else {
nvt_print("HTTP/1.1 200 OK");
nvt_print("Server: cgilaunch");
nvt_print("Connection: close",'');
exec $cgi;
}



Ullrich Horlacher Informationssysteme und Serverbetrieb
Rechenzentrum E-Mail: horlacher@rus.uni-stuttgart.de
Universitaet Stuttgart Tel: ++49-711-685-65868
Allmandring 30 Fax: ++49-711-682357
70550 Stuttgart (Germany) WWW: http://www.rus.uni-stuttgart.de/
 

Lesen sie die antworten

#1 Frank Seitz
20/10/2007 - 08:48 | Warnen spam
Ulli Horlacher wrote:
Ich muss *richtig* *GROSSE* HTTP-uploads verarbeiten. Das kann bis in den
TB-Bereich gehen.

Der Apache (2.0) streikt schon bei laecherlichen 2 GB, also habe ich
selber einen Mini-Webserver (cgilaunch) geschrieben, der im Wesentlichen
nur CGIs startet mit exec($cgi). Meine CGI-Scripte benutzen das Perl
CGI-Modul.

Bei HTTP GET funktioniert das auch einwandfrei,



Wie làdst du denn mit GET Files hoch? Das geht doch garnicht.

nur bei HTTP POST haengen
sich die cgis auf. Ich hab das Problem dann lokalisiert: CGI.pm wertet
leider CONTENT_LENGTH nicht aus, sondern liest bis EOF. Das kommt aber
nicht, der Client haelt die Verbindung offen.



Dann wundert mich, dass CGI.pm mit HTTP 1.1 funktioniert,
denn da wird eine Connection per Default für mehrere Requests genutzt.

Mein Workaround ist nun, dass mein cgilaunch die Daten vom Client liest
und sie via pipe an das cgi-script weiterreichen und nach CONTENT_LENGTH
Bytes die Pipe schliesst (*). Dann bekommt CGI.pm sein EOF und alles
funktioniert.

Leider ist das im GB-Bereich nicht grad effizient. Im top sehe ich, dass
cgilaunch und das cgi-script sich um die CPU pruegeln. Beide sind so bei
knapp 50%.



Das ist nunmal so, wenn zwei Prozesse gleichzeitig zu tun haben.
Jeder normale HTTP-Server ist dem CGI vorgelagert und reicht
die Daten in beide Richtungen weiter.

Es waere also viel besser, wenn das CGI.pm seine Daten direkt vom
Netzwerk-Socket lesen koennte und dabei CONTENT_LENGTH beachten wuerde.
Notfalls patche ich das CGI.pm. Allerdings ist der Code da drin nicht ganz
trivial und ich weiss nicht wo und wie ich das Einlesen entsprechend
modifizieren kann.



Dann wàre das auch nicht anders. CGI.pm liest wie jedes CGI
von STDIN und schreibt nach STDOUT. Auf der anderen Seite ist der
HTTP-Server.

Grüße
Frank
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel

Ähnliche fragen