Hallo,
sicher habt ihr noch meine Speicherprobleme mit xerces,soap und Co. in Erinnerung. Da sich hier in absehbarer Zeit keine Änderung abzeichnet, muss ich das Problem von der anderen Seite angehen. So gibt es jetzt einen Control-Prozess, der u.a. den Speicherverbrauch meines schlimmen Fingers überwacht. Bei einer einstellbaren Grenze gibts ein kill() und danach wird der Prozess neu gestartet. Eigentlich ganz einfach, aber hier komt der Haken:
Ich starte das Program mit 'nohup ./soapserver.pl &' sowohl von der Kommandozeile als auch aus meinem Control-Programm heraus (hier über system). Das gestartet Programm mach einen Port 8081 auf, um zu lauschen. Beim Start aus dem Control-Programm heraus erhalte ich aber die Meldung:
Can't create daemon: Die Adresse wird bereits verwendet at /home/interface/bidi/soapserver.pl line 23
Hmm. Das er beim kill() nicht gleich freigegeben wird, kann ja mal passieren, darum habe ich noch ein sleep(5) zwischen Kill und Start eingebaut. Hilft nix. Es geistert auch kein Zombi in der Prozessliste rum. Mache ich kill und Start über die Shell, brauche ich keine Wartezeit einplanen, der Start klappt immer sofort.
Also, was läuft hier falsch und wie mache ich es richtig? Anbei die drei subs. watchMemory() läuft dabei immer als eigener Process, weil vom Controller geforkt.
########## die Überwachungsroutine ############################## sub watchMemory{ # überwacht Speicherverbrauch vom soapserver.pl und startet ihn bei Bedarf neu my %env_fake; # Start und Stop wollen den Dienstnamen in einem Hash $env_fake{dienst} = "interface"; while(1){ my %res = &getServerInfo(); #print Dumper(%res); if($res{i_online} == 0 ) { print STDERR "Kein Serverprozess da .... \n"; sleep(10); next; } if ($res{i_memory} > $limit && $res{i_status} eq 'sleep'){ print STDERR " zu hoch (max: $limit) .... starte neu .... \n"; &stopServer(%env_fake); sleep(2); # bissel warten, bis Port wieder freigegeben wird &startServer(%env_fake); } sleep(10); } }
############### Stoppen #################### sub stopServer{ # Stoppt soapsever oder connector my $env = shift; my $pattern = $map{ $env->{dienst} }.".pl";
# keine Pattern gefunden? -> raus !! if($pattern eq '.pl'){return;}
my $kill = 0; # counter my $t = new Proc::ProcessTable; foreach my $p(@{$t->table}){ $kill += $p->kill(15) if $p->cmndline =~ /$pattern/ ; } my $res = &getStatus; return $res; }
################# Starten ################### sub startServer{ # starten soapserer oder connector my $env = shift;
if( $map{ $env->{dienst} } eq "soapserver" ){ system ("nohup /home/interface/bidi/soapserver.pl &"); }elsif( $map{ $env->{dienst} } eq "connector" ){ system ("nohup /home/interface/bidi/connector.pl &"); } my $res = &getStatus; return $res; }
Mit freundlichen Grüßen
Jens Puruckherr
Kleiner Nachtrag:
Es wird nicht immer der besetzte Port angemeckert. Einige Male funktioniert der Neustart sehr wohl wie vorgesehen (jetzt gerade 10 mal hintereinander). Beim 11. Mal war wieder Zick ... Soll ich erst prüfen, ob der Port frei ist und dann neu starten?
Mit freundlichen Grüßen
Jens Puruckherr
On Fri, Dec 19, 2003 at 08:42:04AM +0100, Jens Puruckherr wrote:
Das gestartet Programm mach einen Port 8081 auf, um zu lauschen. Beim Start aus dem Control-Programm heraus erhalte ich aber die Meldung:
Can't create daemon: Die Adresse wird bereits verwendet at /home/interface/bidi/soapserver.pl line 23
Da gibt's 'ne Socket-Option. Schau mal nach socket(7) und suche nach SO_REUSEADDR. Warum das so ist, müßtest Du im Stevens nachlesen.
Perl's Socket-Schnittstelle hat dafür m.W. auch schon einen Parameter vorgesehen.
Best regards from Dresden Viele Gruesse aus Dresden Heiko Schlittermann
lug-dd@schlittermann.de writes:
Da gibt's 'ne Socket-Option. Schau mal nach socket(7) und suche nach SO_REUSEADDR. Warum das so ist, müßtest Du im Stevens nachlesen.
Ok, das scheint erst mal zu klappen. Ich sehe, das ich eine Weile kein Socket auf dem Port öffnen kann. Dann ist der Port aber frei und mein Proggi kann gestartet werden :-)
Über die Methode stopServer() und startServer() ist das ganze auch über ein Webinterface bedienbar. Hier tritt der Effekt nie auf, dass der Server sich nicht starten lässt ... nur aus dem MemoryWatcher heraus ...
Mit freundlichen Grüßen
Jens Puruckherr
On Fri, Dec 19, 2003 at 11:11:19AM +0100, Jens Puruckherr wrote:
lug-dd@schlittermann.de writes:
Da gibt's 'ne Socket-Option. Schau mal nach socket(7) und suche nach SO_REUSEADDR. Warum das so ist, müßtest Du im Stevens nachlesen.
Ok, das scheint erst mal zu klappen. Ich sehe, das ich eine Weile kein Socket auf dem Port öffnen kann. Dann ist der Port aber frei und mein Proggi kann gestartet werden :-)
Na, mit dem REUSEADDR müßte es *sofort* wieder gestartet werden können (jedenfalls der Socket läßt sich sofort wieder nutzen)
Über die Methode stopServer() und startServer() ist das ganze auch über ein Webinterface bedienbar. Hier tritt der Effekt nie auf, dass der Server sich nicht starten lässt ... nur aus dem MemoryWatcher heraus ...
Wie - jetzt immer noch?
Heiko
lug-dd@schlittermann.de writes:
Ok, das scheint erst mal zu klappen. Ich sehe, das ich eine Weile kein Socket auf dem Port öffnen kann. Dann ist der Port aber frei
und
mein Proggi kann gestartet werden :-)
Na, mit dem REUSEADDR müßte es *sofort* wieder gestartet werden können (jedenfalls der Socket läßt sich sofort wieder nutzen)
Der Server macht den Port nicht über eine explizite Socket-Operation auf, vielmehr wird er vom Server (SOAP::Lite) irgendwie intern geöffnet. Mit Socket-Optionen ist da nix. Ich versuche nun mit IO::Socket auf den Port zuzugreifen. Sobald das gelingt, starte ich meinen Server.
Mit freundlichen Grüßen
Jens Puruckherr
On Fri, Dec 19, 2003 at 10:32:04AM +0100, Heiko Schlittermann wrote:
On Fri, Dec 19, 2003 at 08:42:04AM +0100, Jens Puruckherr wrote:
Hi,
Can't create daemon: Die Adresse wird bereits verwendet at /home/interface/bidi/soapserver.pl line 23
Da gibt's 'ne Socket-Option. Schau mal nach socket(7) und suche nach SO_REUSEADDR. Warum das so ist, müßtest Du im Stevens nachlesen.
Um sicher zu gehen das alte Pakete die noch im Netz rumirren nicht auf den Port des neuen Prozesses eintreffen.
Ciao, Tobias
On Fri, Dec 19, 2003 at 11:17:09AM +0100, Tobias Koenig wrote:
Um sicher zu gehen das alte Pakete die noch im Netz rumirren nicht auf den Port des neuen Prozesses eintreffen.
Den das aber nicht stören dürfte (wenigstens bei TCP dürfte ja die Application nichts davon bemerken), oder?
Heiko
On Fri, Dec 19, 2003 at 11:27:29AM +0100, Heiko Schlittermann wrote:
On Fri, Dec 19, 2003 at 11:17:09AM +0100, Tobias Koenig wrote:
Hi Heiko,
Um sicher zu gehen das alte Pakete die noch im Netz rumirren nicht auf den Port des neuen Prozesses eintreffen.
Den das aber nicht stören dürfte (wenigstens bei TCP dürfte ja die Application nichts davon bemerken), oder?
Naja, wenn das Paket für einen anderen Server bestimmt war bzw. das Paket ein FIN-Paket ist kann es schon zu seltsamen Effekten führen. Das Problem ist ebend das der Server nicht mitbekommt das es nicht für ihn bestimmt war.
Ciao, Tobias
On Fri, Dec 19, 2003 at 11:55:25AM +0100, Tobias Koenig wrote:
Den das aber nicht stören dürfte (wenigstens bei TCP dürfte ja die Application nichts davon bemerken), oder?
Naja, wenn das Paket für einen anderen Server bestimmt war bzw. das Paket ein FIN-Paket ist kann es schon zu seltsamen Effekten führen. Das Problem ist ebend das der Server nicht mitbekommt das es nicht für ihn bestimmt war.
Und die Sequence-Nummer ... ich würde mal sagen, daß das FIN nur böse ist, wenn's zufällig die (neue) korrekte Sequenznummer hat, oder?
Heiko
On Fri, Dec 19, 2003 at 12:01:42PM +0100, Heiko Schlittermann wrote:
On Fri, Dec 19, 2003 at 11:55:25AM +0100, Tobias Koenig wrote:
Hi Heiko,
Den das aber nicht stören dürfte (wenigstens bei TCP dürfte ja die Application nichts davon bemerken), oder?
Naja, wenn das Paket für einen anderen Server bestimmt war bzw. das Paket ein FIN-Paket ist kann es schon zu seltsamen Effekten führen. Das Problem ist ebend das der Server nicht mitbekommt das es nicht für ihn bestimmt war.
Und die Sequence-Nummer ... ich würde mal sagen, daß das FIN nur böse ist, wenn's zufällig die (neue) korrekte Sequenznummer hat, oder?
Sequenznummer gibt's doch nur bei TCP, oder? (hab Stevens leider gerade nicht hier), aber du kennst ja Murphys Gesetz :)
Ciao, Tobias
On Fri, Dec 19, 2003 at 03:35:17PM +0100, Tobias Koenig wrote:
Und die Sequence-Nummer ... ich würde mal sagen, daß das FIN nur böse ist, wenn's zufällig die (neue) korrekte Sequenznummer hat, oder?
Sequenznummer gibt's doch nur bei TCP, oder? (hab Stevens leider gerade nicht hier), aber du kennst ja Murphys Gesetz :)
Ja - deshalb meinte ich ja - daß es bei TCP die Anwendung nicht bemerken sollte, bei UDP entfällt aber auch das FIN Problem ... und die Anwendung sollte dort allein mit falschen Paketen umgehen können.
Heiko
Ist lange her, ich weiß.
"Jens Puruckherr" jpuruckherr@cyberport.de writes:
Hallo,
sicher habt ihr noch meine Speicherprobleme mit xerces,soap und Co. in Erinnerung.
Mal 'ne ganz blöde Frage:
Was für'n Betriebssystem und was für 'ne Perlversion hast Du eigentlich?
Schonmal die letztmögliche probiert?
Manche Versionen von Perl hatten Memory Leaks, insbesondere auch manche ActivePerl-Versionen.
Steffen
lug-dd@schlittermann.de writes:
Ist lange her, ich weiß.
Wahrlich. Aber immer noch aktuell.
Was für'n Betriebssystem und was für 'ne Perlversion hast Du eigentlich?
5.8.0 auf Linux
Schonmal die letztmögliche probiert?
Das ist dann die .... äh .... www.perl.com ... 5.8.3. Hm, naj, die Maschine ist produktiv, auf der der ganze Kram läuft. da will ich nicht unbedingt jetzt das Perl upgraden. Es sind 'nen haufen selbstkompilierter Module aus dem CPAN dabei. Wenn danach irgenwas nicht mehr funzt, habe ich die Brille auf ...
Manche Versionen von Perl hatten Memory Leaks, insbesondere auch manche ActivePerl-Versionen.
Nuja, die interessieren mich weniger.
Aber mal zum Thema zurück - welches leider noch nicht gegessen ist. - Ich habe Xerces aus der Applikation verbannt. - Ich undefe alles was nicht mehr gebraucht wird an Ort und Stelle (ja, soll eigentlich nicht nötig sein ...) - Ich habe alle Objekte auf irgendwelche zirkulären Referenzen hin untersucht. Alles was verdächtig aussah, wurde geändert.
Im Schnitt hat es ein klein wenig was gebracht, pro XML werden ca. 200 KB Speicher verbraten, die nie wieder kommen. Lustigerweise sinkt der Speicherverbrauch lt 'top' zwischendurch auch mal um ein paar KB, im ganzen jedoch steigt er stetig.
Meinen DBWrapper (der letztenendlich die aus XML erzeugten Objekte in die DB klamüsert) habe ich ich schon abgeklemmt, das hat nicht geholfen. Nun habe ich den XMLHelper im Verdacht. Der macht mittlerweile mit XML::Simple statt mit Xerces aus den XMLs mein Perlobjekte. Ich habe immer eine Instanz $Shop, die ganz viel weiss. Darum muss jedes Objekt und Unterobjekt genau diesen seinen $Shop kennen. Darum gebe ich jeden Objekt einen Hinweis auf seinen $Shop mit auf den Weg. $Objekt = Tolle::Klasse->new($Shop). Alle Zugriffe auf die Shopinterna erfolgen dann nach dem Muster $self->shop->shopid() oder $self->shop->connect(). Vielleicht liegt es daran, dass hier irgendwo eine Referenz klemmt und der Speicher belegt bleibt. Die eigentlichen Artikelklassen möchte ich mal ausschliessen, die sind eher dumm.
Allerdings bringt mich eine Devel::Size auch nicht viel weiter. Mein $Artikel->Objekt, welches aus dem XML resultiert ist ca 10-15% grösser als das XML. Das ist ja OK. Irgendwo werden mir dann aber immer noch 100-150K pro Durchgang geklaut. Vielleicht erbarmt sich mal jemand und hat Lust sich den Code anzuschauen. Was lauffähiges kann ich allerdings nicht präsentieren, da die App. nur intern läuft.
Achso, als letzte Möglichkeit kommt noch Log4Perl in Frage, vielleicht knipse ich das mal aus ...
Mit freundlichen Grüßen
Jens Puruckherr
"Jens Puruckherr" jpuruckherr@cyberport.de writes:
Was für'n Betriebssystem und was für 'ne Perlversion hast Du eigentlich?
5.8.0 auf Linux
Wenn's ein Debian/Sarge ist, sollte die 5.8.2 mit einem apt-get up{dat,grad}e daherkommen. Aber wenn's 'n Debian wär, hättest Du's schon längst gemacht, gell? :-)
Oder einen Zweitrechner zum Entwickeln/Experimentieren aufsetzen; das solltest Du eh' früher oder später tun.
How auch ever, probier mal mit 'nem neueren Perl, dafür sind die da.
Manche Versionen von Perl hatten Memory Leaks, insbesondere auch manche ActivePerl-Versionen.
Nuja, die interessieren mich weniger.
Die Leaks oder die ActivePerl-Versionen? Die Leaks sollten Dich schon interessieren.
Ich habe immer eine Instanz $Shop, die ganz viel weiss. Darum muss jedes Objekt und Unterobjekt genau diesen seinen $Shop kennen.
Du könntest ein kleines Beispielprogramm bauen, das die echte Klasse Shop in ähnlicher Weise verwendet. Diese Klasse erwähnst Du schon länger, vielleicht ist ja wirklich was faul an der, und/oder sie ist zu groß.
Bläht sich auch das Testprogramm auf, zerlegst Du sie in kleinere Module, bis irgendwo der Fehler nackt vor Dir steht.
Die eigentlichen Artikelklassen möchte ich mal ausschliessen, die sind eher dumm.
Die Menge machts. "Artikel" klingt nach vielen Instanzen. Die solltest du nicht voreilig ausschließen.
Auch hier wieder Testprogramm bauen.
Klingt so superschlau, sorry, aber es bleibt Dir wohl nix anderes übrig.
Vielleicht erbarmt sich mal jemand und hat Lust sich den Code anzuschauen.
Hm. Ich glaub' nicht, daß ich mehr als 20 Zeilen fremden Code mal eben so nebenher verstehe. Und es sind sicher paar mehr.
Hast Du nicht jemanden in Deiner Firma, dem Du den Code und die Probleme mal erklären kannst? Das wirkt meist Wunder. Der andere muß nichtmal was von Perl verstehen, nur bissel Zeit mitbringen und Dir zuhören.
Was lauffähiges kann ich allerdings nicht präsentieren, da die App. nur intern läuft.
Doch sicher nur wegen irgendeiner Datenbank, oder? Datenbank mit Testdaten auf'n Schleppi hauen wäre zwar mühselig, aber wenn Du nachher damit rumziehen kannst (z.B. auch mal zu 'nem Perl Monger Treffen; n+2 Augen sehen mehr als 2, n>0), wär's den Aufwand wert.
GreetinX Steffen
Hi Stefan,
lug-dd@schlittermann.de writes:
Wenn's ein Debian/Sarge ist, sollte die 5.8.2 mit einem apt-get up{dat,grad}e daherkommen. Aber wenn's 'n Debian wär, hättest Du's schon längst gemacht, gell? :-)
Naja, ich bin nicht der (verantwortliche) Admin von der Kiste. Ich kann mich zwar su'n, aber wenn was klemmt, habe ich es an der Backe... Und der (verantwortliche) Admin klatscht mir zwar das neue Perl draauf, zuckt aber garantiert nur mit den Schultern wenns hakt: "Du hast mir gesagt, ich soll es tun, was weiss ich schon von deinen Programmen." ... Huuuaaaa. Ich lasse es erst mal.
Oder einen Zweitrechner zum Entwickeln/Experimentieren aufsetzen; das solltest Du eh' früher oder später tun.
Ja, ich muss das ganze mal nach local ziehen ...
How auch ever, probier mal mit 'nem neueren Perl, dafür sind die da.
hmm, ich guck.
Nuja, die interessieren mich weniger.
Die Leaks oder die ActivePerl-Versionen? Die Leaks sollten Dich schon interessieren.
Neee, das Active-Perl natürlich.
Die Menge machts. "Artikel" klingt nach vielen Instanzen. Die solltest du nicht voreilig ausschließen.
Ja, aber pro Durchlauf gibt es immer nur einen Artikel, weil nur einer im XML drinnesteckt.
Klingt so superschlau, sorry, aber es bleibt Dir wohl nix anderes übrig.
Nee, ich weiss ja. letztenendlich muss man auf schnöde Weise alles zu Fuss erkämpfen. Das ist eigentlich immer so, auch wenn vorne dick "Enterprise" drauf steht ...:w
Hm. Ich glaub' nicht, daß ich mehr als 20 Zeilen fremden Code mal eben so nebenher verstehe. Und es sind sicher paar mehr.
ja, war 'ne doofe Idee. Ich würde es auch nicht machen ;-)
Hast Du nicht jemanden in Deiner Firma, dem Du den Code und die Probleme mal erklären kannst?
Da gibts nur einen, aber der ... Also nicht wirklich.
Doch sicher nur wegen irgendeiner Datenbank, oder? Datenbank mit Testdaten auf'n Schleppi hauen wäre zwar mühselig, aber wenn Du nachher damit rumziehen kannst (z.B. auch mal zu 'nem Perl Monger Treffen; n+2 Augen sehen mehr als 2, n>0), wär's den Aufwand wert.
n * 2 wohl eher ;-) Irgendsowas muss aber wohl passieren.
Danke erstmal für die Tipps.
Mit freundlichen Grüßen
Jens Puruckherr
"Jens Puruckherr" jpuruckherr@cyberport.de writes:
lug-dd@schlittermann.de writes:
n+2 Augen sehen mehr als 2, n>0), wär's den Aufwand wert.
n * 2 wohl eher ;-)
Dann muß aber auch n>1 sein.
Couldn't resist. :-)
Steffen
Stefan Lagotzki lago20@gmx.de writes:
Steffen Schwigon wrote:
Dann muß aber auch n>1 sein.
Zu den Augen: Ich hatte zweimal in meiner schulischen Ausbildung einen Lehrer, der ein Glasauge und ein richtiges Auge hatte. Und beide Lehrer haben sehr genau hingesehen, wenn es um Fehler in Mathe bzw. Physik ging.
Ich hatte auch einen. Und der hat auch verdammt gut gesehen. War praktisch Ehrensache, denke ich mal.
Deswegen muß die Formel auch wie im Original "n+2 Augen" heißen, weil "n*2" implizieren würde, daß jeder 2 hätte, in Wirklichkeit aber nur die 2 Augen der ersten Person vorausgesetzt werden können.
GreetinX Steffen
Deswegen muß die Formel auch wie im Original "n+2 Augen" heißen, weil "n*2" implizieren würde, daß jeder 2 hätte, in Wirklichkeit aber nur die 2 Augen der ersten Person vorausgesetzt werden können.
n* [1 .. 2]; n > 0 ? Quatsch:
foreach (1 .. n) { $augen += getAnzahlAugen($_); }
Wobei 1 .. n natürlich je eine anwesende Person kennzeichnet.
n+2 Augen sehen mehr als 2, n>0)
n + 2 heisst dann, dass bei einer Person 3 Augen gucken würden?
Mit freundlichen Grüßen
Jens Puruckherr
"Jens Puruckherr" jpuruckherr@cyberport.de writes:
Wobei 1 .. n natürlich je eine anwesende Person kennzeichnet.
n+2 Augen sehen mehr als 2, n>0)
n + 2 heisst dann, dass bei einer Person 3 Augen gucken würden?
Das Problem einer ungetypten Sprache wie Perl. Eine "strict old aunt of a compiler" würde streiken, wenn n einmal für Anzahl Personen und einmal Anzahl Augen verwendet, bzw. nicht typkonform addiert würde.
GreetinX Steffen
lug-dd@mailman.schlittermann.de