Hi all,
bin gerade an einer (für mich) harten Nuss dran. Haben hier eine über 10
Jahre alte, aber sehr wichtige Legacy Applikation (in C++ geschrieben),
wo ein C++ XML Server (http://xerces.apache.org/xerces-c/) drauf läuft,
OS ist IBM AIX 7.
Auf dem selben Server läuft ein Apache Tomcat 8.5 um 10 verschiedene
SOAP Requesttypen und Responsetypen (z.B. so Dinge wie Info, Update,
Delete etc. etc.) zu empfangen und zurück zu geben an eine externe
Applikation (alles in der selben Firma, im Intranet).
Momentan verschone ich euch mit den weiteren Details, es geht darum, das
Kernproblem zu begreifen bzw. zu analysieren. Das Problem ist, dass
dieser XML Server in C++ geschrieben, immer wieder mal crashed (evtl.
Memory Leak) und der Tomcat nach einem definierten Timeout z.B. 10s.
dann natürlich keine Antwort bekommt und mit "Caused by:
java.net.SocketTimeoutException: Read timed out" crashed.
Eine Idee, war den Timeout zu erhöhen, aber das bringt ja nichts, da
keine Antwort mehr kommt aufgrund des xml-Server-Crashes (die C++
Implementierung). Aktuell haben wir ein Skript am Laufen, dass den
Tomcat bei solchen Fehlern immer wieder mal restartet, was auch nicht
langfristig eine Lösung ist.
Die Idee ist jetzt, das Problem einzugrenzen. D.h. Pro Requesttyp (es
sind 10 verschiedene) auf xml-Server Seite 10 Instanzen mit jeweils
einer Port-Nr. (eigener Socket ist das, oder?) zu erstellen. D.h. für
jeden Request einen eigenen Port. Der Tomcat bekommt die Requests sendet
z.B. den Requesttyp A (z.B. Info) an Port 10000, Requesttyp B (z.B.
Update) an Port 10001 usw.
Der Tomcat sendet den Requesttyp einfach an den richtigen Port und
empfängt die Response wieder und sendet sie weiter (SOAP xml).
Ist das überhaupt möglich? Damit könnte herausgefunden werden, welcher
Requesttyp immer wieder crasht und man könnte es eingrenzen und mal
etwas stabilisieren.
Braucht der Tomcat da auch 10 verschiedene Instanzen der gleichen
Applikation? Nicht oder?
klausi
ich würde ein oder zwei Schritte zurück gehen
klausi schrieb:> d der Tomcat nach einem definierten Timeout z.B. 10s. dann natürlich> keine Antwort bekommt und mit "Caused by:> java.net.SocketTimeoutException: Read timed out" crashed.
Ist das nur der Tomcat oder läuft da noch eine Application drauf? Und
eine Socket-Exception sollte eigentlich nicht den Tomcat crashen,
sondern nur zu einer Fehlerrückmeldung -- die ggf. auch Schweigen ist --
führen.
Das "Caused by" deutet auf einen längeren Stacktrace hin, in dem viele
Infos stecken.
Vielleicht müsste man ein gescheites Logging des Tomcat aktivieren.
klausi schrieb:> Das Problem ist, dass> dieser XML Server in C++ geschrieben, immer wieder mal crashed
Dann such den echten Fehler dort ihn und löse das Problem (Problem 1).
Logfile des Servers lesen. Debuger anwerfen, Coredump analysieren. Gibt
es valgrind für AIX? Dann valgrind, sonst purify. Debug malloc. Nicht zu
vergessen Desk-Checks.
> der Tomcat nach einem definierten Timeout z.B. 10s.> dann natürlich keine Antwort bekommt und mit "Caused by:> java.net.SocketTimeoutException: Read timed out" crashed.
Seit wann stürzt ein Tomcat ab? Aber gut, löse auch das Problem (Problem
2). Einfach mal den Stacktrace der Exception ansehen und um den
Socket-Aufruf eine anständige Fehlerbehandlung mit try/catch bauen, die
das Servlet in einem definierten Zustand verlässt.
> Aktuell haben wir ein Skript am Laufen, dass den> Tomcat bei solchen Fehlern immer wieder mal restartet, was auch nicht> langfristig eine Lösung ist.
Das ist auch kurzfristig keine Lösung, das ist Blödsinn. Statt Problem 1
und 2 zu lösen baust du dir noch Problem 3 ein. Such die Fehler statt
Ausreden zu finden wie du um die Fehlersuche herum kommst.
> Die Idee ist jetzt, das Problem einzugrenzen.
Das ganze Zeug was du machen willst ist Bullshit.
> auf xml-Server Seite 10 Instanzen mit jeweils> einer Port-Nr. (eigener Socket ist das, oder?) zu erstellen.
Das heißt, du willst Problem 1 verzehnfachen. Dann hast du insgesamt 12
Problemen. Gratulation. Such den Fehler mit anständigen
Fehlersuchtechniken, statt solchem Rumstochern.
> Damit könnte herausgefunden werden, welcher> Requesttyp immer wieder crasht
Man könnte auch einfach mal in die Logfiles und den Coredump sehen. Aber
lass mich raten, irgend ein Held hat die Logs des Servers und Coredumps
ausgeschaltet, weil die ja alle scheiße sind?
Finde die Ursache. Von daher C++ Debugging.
Und wenn du mit cores nicht weiter kommst könntest du auch mal einen
backtrace versuchen.
man 3 backtrace
Ich habe bei einer Applikation mal einen Signal-Handler installiert, der
wiederum dann die Backtrace-Funktionen aufgerufen hat.
So konnte das Programm bei Absturz die fehlerhaften Funktionen
wenigstens noch in ein Log schreiben. Hatte damals geholfen, weil für
die cores kein Platz verfügbar war.
Es geht primär um deine Erfahrung und Umgebung in der du dich befindest
- damit wir eine für dich passende Lösung anbieten können - bisher
wissen wir nichts über dein Können und nur ein ganz kleines bisschen
über dein System - Problem damit ist: Wir Profis wissen genau wie lange
wir für den einen oder anderen Punkt braucht - wenn du ein Frischling
bist wird du dich dank fehlender Erfahrung immer für den am
"einfachsten" wirkenden Weg entscheiden - der tatsächlich ein vielfaches
der Zeit kosten könnte
der normale Weg so was zu lösen wäre:
1. Die Komponenten zerlegen
-kann man den C++-Server autark angreifen, oder muss der immer unter dem
Tomcat laufen
-nicht alles gleichzeitig analysieren sondern jede Komponenten einzeln
2. die Fehlerrate drastisch erhöhen
-mit einem Test-Tool das zig-tausend mal mehr Anfragen an den Server in
Zeit 0 stellt als jemals üblich, damit wird der oder "die" Fehler viel
stärker auftreten und man erkennt schneller ob die Fixes greifen(oder
mehr Probleme verursachen)
3. die richtigen Tools verwenden
-statische Analyse mit CppCheck und PVS-Studio - Quelltext einfach unter
Windows/Linux prüfen
-AdressSanitizer aus dem gcc/clang (ab gcc 4.8 unklar ob für AIX
verfügbar)
und/oder Valgrind für Runtime-Analyse
-direkte manuelle Analyse des Codes
also mal Fakten auf den Tisch:
1. Welche C/C++, AIX/Linux Erfahrung hast du?
-wie viele Jahre C/C++ - es macht für unsere Tips ein riesen Unterschied
ob du seit 20 Jahren mit C++ am Start bist oder ob das dein 1. Projekt
in C++ oder überhaupt mit "Programmierung" ist, was ist deine
Primäsprache, kennst du dich mit AIX gut aus, Linux?
2. Was ist das für ein System (Linux wäre simple, AIX kann ein Problem
sein weil es proprietär ist und nicht ganz so einfach die übliche Tools
unterstützt)
-welcher Kompiler gcc/clang/xl? (Version ist sehr wichtig - viele Tools
gibt es erst/oder werden besser in späteren Versionen)
-Xerces-C Version? baust du die lib selber?
-hast du Valgrind und AdressSanitizer?
-Kannst du auch unter Linux bauen (manche Entwickler machen das auch
Testgründen - vieleicht ist das bei euch auch so)?
-> damit könnte man eine viel breitere/besser Menge an Tools verwenden
-Arbeitest du in einer IDE oder alles mit make auf der Konsole?
3. zum C++ Teil
-Kannst du den C++ Teil selbst bauen? hast du Zugriff auf
Kompile-Settings usw.?
-Kannst du den C++ Teil frei vom Tomcat laufen lassen und testen?
-Kannst du den C++ Teil einfach debuggen?
Jetzt wird zu jedem ? eine Antwort erwartet :)
Xerces ist ein XML Parser, wie spricht Tomcat mit der C++ Applikation?
Ist das ein Webapp die vieleicht noch etwas wie XML-RPC macht oder ist
Tomcat nur als HTTP Proxy dazwischen?
Neben den anderen sinnvollen Tipps oben würde ich auch das Logging im
Tomcat einschalten/hochdrehen und hier schauen ob eine bestimmte SOAP
Action crasht oder es ggf. ein generelles (OOM?) Problem gibt. Handelt
es sich um eine einzelne Aktion könnte hier weiter runter gehen und auch
die Payload loggen. Wie ich verstehe ist es eine Produktionsumgebung, da
wäre noch interessant wie die Last ist - Logging einschalten auf einem
System unter Hochlast könnte kontraprdouktiv sein... :-)
Vielen Dank für euer zahlreiches Feedback! Konnte mir noch ein paar
Gedanken machen, das hat geholfen.
Ich gebe euch nächstens noch mehr Details und werde etwas
spezifischer. Meistens sind im 1. Post zuviele Details zu verwirrend und
das macht oft Probleme / Missverständnisse. Step by step / iteration ist
besser.
Nur kurz zu mir: ich habe an den beiden 10-20J. alten Legacy-Systemen
nicht wirklich entwickelt, Ich habe nun als neuer Systemanalyst bzw.
Architekt (diese alte Lösung wird abgelöst) die dankbare Aufgabe
gefasst, die Schnittstelle zu analysieren. Die alten Entwickler (ältere
Semester) sind nicht mehr in der Firma, bzw. 1-2 Leute kenn ich noch die
daran entwickelt haben.
Ich denke auch daran, einen neuen Ansatz wie "Design Thinking" zu
verwenden, um zuerst mal das Problem genau zu verstehen, mit den älteren
Entwicklern, und Lösungen zu generieren. Die wissen es nämlich auch
nicht und die Aufteilung der Requesttypen in mehrere Instanzen auf C++
XML Serverseite war zuerst mal deren Idee, um den Ursachen-Requesttyp /
oder Instanz eingrenzen zu können.
Und klar, Zerteilung in Teilprobleme ist sehr hilfreich für die Analyse.
Die C++ XML Serverimplementierung kommuniziert über Sockets (TCP/IP) /
Thread-Pooling mit Tomcat. Es ist eine Webapp die auf Apache Tomcat
läuft, XML-RPC macht und eingehende SOAP Requests (WSDL) empfängt,
transformiert und weiterleitet an den XML C++ Server und wiederum auf
dieselbe Transaction-ID eine Response zurückbekommt und die wieder
zurück gibt an die externe Applikation.
Mir gelang es nun, zuerst den Tomcat heute im Detail genauer zu
analysieren, die Webapp/Tomcat in DEBUG Logging (log4j) zu schalten und
mit einem Simulationstool (SOAP UI) Soap XML Requests zu simulieren, und
siehe da ich kann den Fehler der in PRODUCTION auftaucht nun auch in der
DEV-Umgebung simulieren. Das ist schon mal sehr gut.
Habe etwas mehr Erfahrung in der Java Welt / mit Tomcat drum habe ich
jetzt mal mit dieser Komponente begonnen. C++ Coredump Mem-Analysen
werden noch folgen...
Ich selbst habe einige Jahre Erfahrung in C / Java, habe mich aber seit
ein paar Jahren auf Daten- und Systemanalysen konzentriert, bzw.
Software-Architektur / Big Data (splunk etc.) / Konzeptionelle Arbeit
(z.B. Requirements-Eng.) in einem Projekt. Aber kein Problem, ich
brauche halt etwas Zeit um mich in etwas "älteren Zeugs" einzuarbeiten,
vor allem was andere Leute zuerst fabriziert haben, deswegen
faszinieren/begeistern mich Green-Field Projekte in der Forschung / Uni
eben schon um einiges mehr... wo ich zusmamen mit Leuten an den
Konzepten und der Implementierung bis zum Schluss arbeiten kann, in
einem Forschungsprojekt oder auch alleine als Hobby z.B. (R, python). In
einer Firma kann man es sich eben nicht aussuchen ;-)
Soweit mal dazu... Komme noch mit mehr Details... bzw. gehe dann
spezifisch auf eure Fragen ein.
klausi
klausi schrieb:> Aber kein Problem, ich> brauche halt etwas Zeit um mich in etwas "älteren Zeugs" einzuarbeiten,> vor allem was andere Leute zuerst fabriziert haben, deswegen> faszinieren/begeistern mich Green-Field Projekte in der Forschung / Uni> eben schon um einiges mehr
nicht so viel von "Green-Field" Projekten, "älteren Zeugs" und "ältere
Semester" schreiben sonst denke wir noch das du so ein Jungspund bist
der eben kaum Erfahrung hat - weil genau so reden die - Männer werden
auf dem Schlachtfeld geformt und nicht beim Kaffeekränzchen, mit dem
schönen neuen Besteckt :)
cppbert schrieb:> klausi schrieb:>> Aber kein Problem, ich>> brauche halt etwas Zeit um mich in etwas "älteren Zeugs" einzuarbeiten,>> vor allem was andere Leute zuerst fabriziert haben, deswegen>> faszinieren/begeistern mich Green-Field Projekte in der Forschung / Uni>> eben schon um einiges mehr>> nicht so viel von "Green-Field" Projekten, "älteren Zeugs" und "ältere> Semester" schreiben sonst denke wir noch das du so ein Jungspund bist> der eben kaum Erfahrung hat - weil genau so reden die - Männer werden> auf dem Schlachtfeld geformt und nicht beim Kaffeekränzchen, mit dem> schönen neuen Besteckt :)
Naja, wer SOAP und xml als älteres Zeug bezeichnet, hat sich ja zeitlich
einigermaßen eingeordnet. Da geht nur "grüne Wiese" und nicht
"fruchtbarer Acker".
Carl D. schrieb:> Naja, wer SOAP und xml als älteres Zeug bezeichnet, hat sich ja zeitlich> einigermaßen eingeordnet. Da geht nur "grüne Wiese" und nicht> "fruchtbarer Acker".
SOAP. Äh... ja. BTDT, burnt the shirt.
Diese verrückten Kids machen das heute anders. Die haben diese Dinger,
äh, Message Queues.
Leider hilft das dem TO auch nicht weiter, aber das können wir bislang
IMHO ja auch nicht, glaub ich. ^(".)^
Also, wenn ich das richtig verstanden habe, gibt es eine
Java-Webapplikation, die in Apache Tomcat läuft. Diese
Java-Webapplikation nimmt (wie?) von einem Client (was für einen?) Daten
über HTTP oder HTTPS (wirklich?) entgegen.
Dann werden die gesendeten Daten über eine Socket-Connection (1) von der
Java-Applikation an eine Software übergeben, die (dem TO zufolge)
irgendwas mit dem Parser Xerxes zu tun haben soll und in C++ entwickelt
wurde.
Klar, kluge und erfahrene Leute setzen an der Wurzel an. Die scheint
hier das C++-Programm zu sein, welches laut TO häufiger den Dienst
verweigert. Der TO vermutet, daß dort ein Memory Leak vorliegt. Er
möchte das "Problem" lösen, indem er aus dem einen Prozeß viele macht.
Leider ist das (Amdahl's Law) (sehr weitgehend) unsinnig bei einem
weitestgehend linearen Black-Box-Prozeß. Der TO kann aber wohl kein C++,
und / oder hat keinen Zugriff auf die Sourcen, oder versteht sie nicht.
Ich bezweifele aber erheblich, daß die Ideen des TO seine Lage
verbessern würden. Ohne detaillierte Testergebnisse vorweisen zu können,
behaupte ich mal: ob jetzt einer oder drölfzehn Prozesse auf derselben
Maschine um genau dieselbe langsamen Ressourcen konkurrieren, hat
keinerlei Vorteile... Im Gegenteil: contextswitches sind leider unter
allen modernen Betriebssystemen teuer. Der TO geht also in die flahsce
Richtung, fürchte ich.
Ach ja, lieber TO: vielleicht hilft ja ein Blick in die Logdateien. :-)
(1) SOAP fiel im Thread, oder noch XML-RPC?
Ich weiss ja nicht was dieser in C++ implementierte SOAP-Dienst unter
der Haube genau macht was er für Daten generiert, wo die herkommen und
der evt. spezielle Libs nutzt die nur unter C++ verfügbar sind, ... und
ob der Dienst noch von Dritten Anwendungen genutzt wird oder nur von
dieser Tomcatwebanwendung.
Je nachdem was oben (nicht) zutrifft würde ich darüber nachdenken das
Ganze
1. In deine tomcatbasierte Webanwendung einzubauen, dann fällt das ganze
SOAP-Geraffel gleich mal weg.
2. Den C++ Dienst in Java umzusetzen. Das wird evt. schneller und
einfacher
sein als ohne Erfahrung unter AIX und C++ dieses Programm zu debuggen
und zu fixen.
klausi schrieb:>SOAP Requesttypen und Responsetypen (z.B. so Dinge wie Info, Update,>Delete etc. etc.) zu empfangen und zurück zu geben an eine externe>Applikation (alles in der selben Firma, im Intranet).
neu schreiben und nicht versuchen das alte gefrikelte System am Leben zu
erhalten wird wohl günstiger sein. Sourcen haste ja.
Es ist zwar löblich das alte versuchen am Leben zu erhalten aber
Aufgrund der Entwicklung der Software und Hardware (PC) wird es hier
einfacher zu sein die Entwicklung auf AIX sterben zu lassen Aufgrung
mangelnder Kenntnisse und Neuentwicklung da die sourcen ja vorhanden
sind (Requesttypen und Responsetypen)neu zu programmieren. Die Wartung
der AIX Systeme hast du noch nicht bedacht denn wer kennt AIX Systeme
noch.
Jetzt ist der Zeitpunkt das zu Ändern, zukünftig wird das noch teurer
werden.
cppbert schrieb:> nicht so viel von "Green-Field" Projekten, "älteren Zeugs" und "ältere> Semester" schreiben sonst denke wir noch das du so ein Jungspund bist> der eben kaum Erfahrung hat
Naja, er hat trotz einiger Jahre Erfahrung in Java jetzt erst den
log4j-Schalter gefunden.
Wahrscheinlich ist es nur eine Kleinigkeit. Die "alten Entwickler" haben
wohl keine Zeit/Lust sich das anzusehen, und schauen mal was der junge
"Architekt" so drauf hat.
Bin mir nicht sicher, ob ein "Design Thinking"-Ansatz hier das Richtige
ist. Reproduzierbar ist der Absturz ja schon einmal, damit hat man meist
schon gewonnen.
hallo zusammen,
jaja... macht euch nur lustig, danke für eure Comments. Macht ja Spass,
das zu lesen.
Nein... ihr habt mich wohl missverstanden, aber glaubt nicht alles, was
ihr denkt ;-). Ja, ich habe ein paar Jahre Java und C Erfahrung (nicht
unbedingt C++), auch nach der Uni sammeln können, das ist nicht das
Problem. Das Problem ist eher, ich muss mich erst in (wenigstens
Teilbereiche) Code (Java UND C++) einarbeiten, Leute haben da fast 20
Jahre dran gearbeitet, dementsprechend ist auch der Umfang, das dauert
halt ein wenig.
Fakt ist:
Das Problem wurde in mehrere Teilprobleme aufgeteilt.
Arbeitshypothese: memory-leak Problem in der XML Service Implementierung
auf C++ Komponente, Auswirkungen auf Tomcat (Request- und Response
Timeouts zu Drittsystem), die Tomcat-Webservice Implementierung ist
(vermutlich) nicht das Hauptproblem, jedoch muss min. das
Exceptionhandlung verbessert und die Webapp ebenso analysiert werden
(der ganze Prozess / Request/Response End-to-End).
Zur Zusammenfassung:
Auf Server A läuft (IBM AIX 7).
- C++ Core Applikation
- C++ / XML Service Implementation
- Tomcat / Webapp, die XML-RPC macht SOAP Schnittstelle zur
Drittapplikation (HTTPS) , d.h. Tomcat kommuniziert im Localhost mit der
C++ Appl XML Service Implementation, bekommt Requests von der
Drittapplikation, C++ / XML Service Impl. sendet Responses zurück an den
Tomcat, der leitet sie zurück an die Drittapplikation.
Server B:
- Drittapplikation sendet via HTTPS Soap Requests an Tomcat zu Server A.
- Zw. Server A und B wirkt auch noch ein Loadbalancer (Server A gibt es
zweimal (mirrored), also Server A1 und A2.
In Produktion haben wir nur (sehr) eingeschränkte Rechte. In
Entwicklungs- bzw. Testumgebung lässt sich eine solche Last nur
simulieren. Ich konnte mittels einem Tool (SoapUI) eine Last simulieren,
deswg. konnte auch erst jetzt etwas geloggt werden, Loglevl auf
Debugging einstellen ist nicht das Problem..., eher wie simuliere ich
bzw. kann ich den Fehler nachstellen. Und das ist jetzt mal geschafft.
Debug Level ist natürlich überall eingeschaltet. Die Idee, die XML
Services je nach Requesttyp auf multiple XML Serviceinstanzen je nach
Typ aufzusplitten, stammt von den Entwicklern, nicht von mir, die
Intention ist nicht damit das Problem zu lösen, sondern einzugrenzen
bzw. welcher Reqesttyp macht Probleme um damit das Memoryleak
eingrenzen/beobachten zu können, und ist natürlich nicht die Lösung per
se. Die Entwickler konnten nämlich das Memoryleak jahrelang nicht
finden. Den C++ Teil werden wir natürlich so bald wie möglich auch mit
einem geeignet Tool (purify etc.), Memorydiagnosen usw. durchführen.
Auf Tomcatseite habe ich das Exceptionhandling jetzt erstmal verbessert,
bei Read timed out, wird der Socket kontrolliert geschlossen.
So, jetzt sehe ich mir den C++ Teil an, und versuche herauszubekommen;
warum die MemoryLeak Detection so schwierig bzw. bisher nicht
erfolgreich war.
Aber: ruhig Blut! Eins nach dem anderen! Leider ist das nicht mein
einziges "Projekt"!
Es ist auch ein Problem mit zeitl. Ressourcen (fürs Management ist
leider immer alles Prio 1 -> heisst eigentlich, alles ist genauso
wichtig, nichts ist wichtig ). wir sind natürlich schon am Konzept /
Requ. Engineering eine neuen Lösung, das dauert aber, und wie immer:
Produktion geht vor... klausi ist dran...
klausi
P.S. nachdem wir dann (hoffentlich) das Memoryleak eingrenzen und
analysieren können, werden wir auch noch evtl. die Libs aktualisieren
(xml-xerces); ich sehe im C++ Source (Kommentar) dass es da schon einige
Bugfixes und Analysen gab. Aber der Schritt.. kommt später!
klausi schrieb:> Fakt ist:> Das Problem wurde in mehrere Teilprobleme aufgeteilt.
Das ist ja schonmal ein guter Ansatz.
> Arbeitshypothese: memory-leak Problem in der XML Service Implementierung> auf C++ Komponente
Nun, C- und C++-Programme sind für eine gewisse... Empfindlichkeit beim
Handling von Memory-Issues bekannt. Wenn dabei etwas schief läuft, kann
es verschiedene Ursachen haben und obendrein nicht ganz einfach zu
debuggen sein, gerade wenn der Fehler nur in bestimmten Corner Cases
auftritt.
Warum Ihr Euch so auf ein Memleak versteift, ist mir zudem schleierhaft.
Gibt es darauf irgendwelche Hinweise? Zum Beispiel im Monitoring, das in
einer Produktion doch sicherlich verwendet wird?
Ich ganz persönlich würde daher zunächst einmal ermitteln, ob das
Problem wirklich ein Memleak ist. Das sollte nicht allzu schwierig sein,
denn selbstverständlich kann man systemseitig periodisch auf den Prozeß
schauen und stellt dann schnell fest, ob der Prozeß im Laufe seiner
Lebenszeit immer mehr Speicher braucht. Dazu gibt es ein paar bewährte
Möglichkeiten, eine Auswahl:
- Das Logging des Betriebssystems sollte eine Logmessage erzeugen, wenn
ein Prozeß
wegen eines Out-Of-Memory gekillt wird.
- der System Activity Reporter (sar) sammelt periodisch die
Performancecounter
des Betriebssystemkernels ein, inklusive Speicherauslastung.
- Das System Accounting sammelt periodisch Daten über die Aktivitäten
von Prozessen
und Benutzern, sowie deren Ressourcennutzung.
- Eine ganz einfache Methode wäre es, mit Cron ein kleines Skript zu
starten, das
aus der Prozeßtabelle und / oder dem /proc-Dateisystem den gesuchten
Prozeß und
seine Speichernutzung ausliest und irgendwohin mit Zeitstempel
wegschreibt...
> Zur Zusammenfassung:> Auf Server A läuft (IBM AIX 7).> - C++ Core Applikation> - C++ / XML Service Implementation> - Tomcat / Webapp, die XML-RPC macht SOAP Schnittstelle zur> Drittapplikation (HTTPS) , d.h. Tomcat kommuniziert im Localhost mit der> C++ Appl XML Service Implementation, bekommt Requests von der> Drittapplikation, C++ / XML Service Impl. sendet Responses zurück an den> Tomcat, der leitet sie zurück an die Drittapplikation.> [...]> Debug Level ist natürlich überall eingeschaltet. Die Idee, die XML> Services je nach Requesttyp auf multiple XML Serviceinstanzen je nach> Typ aufzusplitten, stammt von den Entwicklern, nicht von mir, die> Intention ist nicht damit das Problem zu lösen, sondern einzugrenzen> bzw. welcher Reqesttyp macht Probleme um damit das Memoryleak> eingrenzen/beobachten zu können, und ist natürlich nicht die Lösung per> se. Die Entwickler konnten nämlich das Memoryleak jahrelang nicht> finden.
... was IMHO eher darauf hindeutet, daß das Problem womöglich doch kein
Memleak ist.
> Den C++ Teil werden wir natürlich so bald wie möglich auch mit> einem geeignet Tool (purify etc.), Memorydiagnosen usw. durchführen.
Warum eigentlich C++? Höchstwahrscheinlich wäre ein ordentliches Skript
in einer modernen Skriptsprache nicht wesentlich langsamer, aber dafür
wesentlich einfacher zu warten und zu debuggen. Bei einem Dienst, der
über das Netzwerk angesprochen wird, dürfte ohnehin das Netzwerk der
Flaschenhals sein, und zum Beispiel Python verfügt über ausgesprochen
performante XML-, XML-RPC- und SOAP-Bibliotheken...
Wo wir gerade so schön dabei sind: natürlich könnte man mit einem
kleinen Skript in einer modernen Skriptsprache auch eine Art Wrapper und
/ oder sogar einen kleinen Supervisor implementieren, der anstelle des
tatsächlichen SOAP-Service angesprochen wird, die Requests als auch den
Zustand des "echten" SOAP-Service vor und nach den Requests loggt, und
die Requests dann erst an den "echten" Soap-Service übergibt (sowie die
Response an die aufrufende Applikation zurückgibt)...
Nur so ein paar Gedanken... HTH, YMMV.
klausi schrieb:> P.S. nachdem wir dann (hoffentlich) das Memoryleak eingrenzen und> analysieren können, werden wir auch noch evtl. die Libs aktualisieren> (xml-xerces); ich sehe im C++ Source (Kommentar) dass es da schon einige> Bugfixes und Analysen gab. Aber der Schritt.. kommt später!
Sind die Request/Response Pakete fixer grösse?
Wie viele verschiedene Request/Response Typen gibt es?
Somit ist es schon Fr. Abend.. und komme ich noch dazu, ein bisschen
Feedback zu schreiben :)
Kurzfassung (Mgmt. Summary):
- bis jetzt wurden im C++ Teil (XML Server Instanzen) keine Mem-Leaks
entdeckt, auch nicht in Prod. Umgebung
- auch Lastsimulationen / Tests zeigten bezgl. C++ Teil (XML Server
Instanzen) auch keine Beschwerden
- Wg. Cronjob mit Prozess-Size rausloggen: hab das Log gefunden, das
wird schon gemacht (der langjährige Entwickler hat mir das nicht
mitgeteilt), aber er hat gesagt, dass diesbezgl. in PROD schon länger
keine Mem-Leaks aufgetreten sind bezgl. C++ Teil
- Es gibt niemanden der sich noch mit dem Tomcat Teil beschäftigt / Know
how hat, ausser mir momentan
- Tomcat Java / Webapp konnte ich mit Lasttest-Simulationen den Fehler
nachstellen; es sieht so aus dass eine Response nicht korrekt auf die
Request ID zurückkommt/matcht im Fehlerfall, daher wird nach dem
definierten Timeout eine Errormeldung/Exception "Read timed out"
geworfen, da solange auf eine richtige Antwort gewartet wird, aber nie
eine ankommt
-> d.h. Fehlerhandling verbessern
- Tomcat / Mem-Leak: darüber hinaus konnte ich ein Mem-Leak auch in der
Java Implementierung feststellen: Input- und Outputstreams werden nicht
korrekt mit flush() und close() geschlossen. Ein Garbage Collector (GC)
Analyse Tool von IBM bzw. Eclipse MAT zeigte mir dass der Heap
kontinuierlich ansteigt. Versuche noch in der Testumgebung einen OOM
Error zu produzieren.
-> d.h. Implementierung optimieren
Nun die Antworten auf eure Comments ;-)
cppbert schrieb:> Sind die Request/Response Pakete fixer grösse?
meines Wissens ja, prüfe ich aber nochmal.
> Wie viele verschiedene Request/Response Typen gibt es?
10 momentan.
Sheeva P. schrieb:> Warum eigentlich C++? Höchstwahrscheinlich wäre ein ordentliches Skript> in einer modernen Skriptsprache nicht wesentlich langsamer, aber dafür> wesentlich einfacher zu warten und zu debuggen.
Historisch gewachsen, mehr als eine Dekade lang. Kern C++ Applikation
wohl > sehr viele hunderttausende / Millionen (?) LOC.
Sheeva P. schrieb:> - Eine ganz einfache Methode wäre es, mit Cron ein kleines Skript zu> starten, das> aus der Prozeßtabelle und / oder dem /proc-Dateisystem den gesuchten> Prozeß und> seine Speichernutzung ausliest und irgendwohin mit Zeitstempel> wegschreibt...
Wie beschrieben.. wird schon gemacht. und ja, bis jetzt tatsächlich
keine Mem-Probleme im C++ Teil.
Sheeva P. schrieb:> Warum Ihr Euch so auf ein Memleak versteift, ist mir zudem schleierhaft.> Gibt es darauf irgendwelche Hinweise? Zum Beispiel im Monitoring, das in> einer Produktion doch sicherlich verwendet wird?
Laut Entwickler sind vor einiger Zeit (Monate?) Probleme aufgetreten, es
wurde vieles gefixt, bisher nicht mehr, das ist richtig. Aber wie
beschrieben es hat gezeigt dass auf Tomcat/Java Seite (!) ein Mem-Leak
auftritt.
Sheeva P. schrieb:> ... was IMHO eher darauf hindeutet, daß das Problem womöglich doch kein> Memleak ist.
Ja, höchstwahrscheinlich.
Chris K. schrieb:> Jetzt ist der Zeitpunkt das zu Ändern, zukünftig wird das noch teurer> werden.
Ja ein grösseres Projekt ist dran (meherere Millionen) die gesamte
Kern-Applikation inkl. diesen Teilen abzulösen. Geht halt nicht von heut
auf morgen.
cppbert schrieb:> Männer werden> auf dem Schlachtfeld geformt und nicht beim Kaffeekränzchen, mit dem> schönen neuen Besteckt :)
Absolut! Meine Erfahrung in C, Programmierung von Leitsystemen: 3 Jahre
auf IBN ;-)
cppbert schrieb:> der normale Weg so was zu lösen wäre:>> 1. Die Komponenten zerlegen> -kann man den C++-Server autark angreifen, oder muss der immer unter dem> Tomcat laufen> -nicht alles gleichzeitig analysieren sondern jede Komponenten einzeln
jep, Tomcat hat aktuell Vorrang. Die Analysen haben gezeigt, dass da
eher die Ursache liegen könnte
> 2. die Fehlerrate drastisch erhöhen> -mit einem Test-Tool das zig-tausend mal mehr Anfragen an den Server in> Zeit 0 stellt als jemals üblich, damit wird der oder "die" Fehler viel> stärker auftreten und man erkennt schneller ob die Fixes greifen(oder> mehr Probleme verursachen)
ja, Test Load-Simulationen Stresstests führe ich gerade durch
>> 3. die richtigen Tools verwenden> -statische Analyse mit CppCheck und PVS-Studio - Quelltext einfach unter> Windows/Linux prüfen
haben wir
> -AdressSanitizer aus dem gcc/clang (ab gcc 4.8 unklar ob für AIX> verfügbar)> und/oder Valgrind für Runtime-Analyse> -direkte manuelle Analyse des Codes
Analysiere gerade den Java Teil, inkl. statischer Code Analyse, manuelle
Analyse und Garbage Collector Analysen (mit einem IBM Tool) und Eclipse
MAT
>> also mal Fakten auf den Tisch:>> 1. Welche C/C++, AIX/Linux Erfahrung hast du?> -wie viele Jahre C/C++ - es macht für unsere Tips ein riesen Unterschied> ob du seit 20 Jahren mit C++ am Start bist oder ob das dein 1. Projekt> in C++ oder überhaupt mit "Programmierung" ist, was ist deine> Primäsprache, kennst du dich mit AIX gut aus, Linux?
AIX gut, beruflich mehrere Jahre, und als ersten Job nach dem Studium 3
Jahre als C Entwickler gearbeitet, immer viel auch mit Datenbanken
(Oracle)
Linux auch mehrere Jahre, auch als Hobby (Home Emulations etc.
Projekte, auch auf Github)
Primärsprache doch eher Java, aber bin heute und in den letzten Jahren
sehr viel in Datenanalysen unterwegs (python, R, SQL etc.)
>> 2. Was ist das für ein System (Linux wäre simple, AIX kann ein Problem> sein weil es proprietär ist und nicht ganz so einfach die übliche Tools> unterstützt)
AIX 7
> -welcher Kompiler gcc/clang/xl? (Version ist sehr wichtig - viele Tools> gibt es erst/oder werden besser in späteren Versionen)
gcc, Version muss ich noch kucken
> -Xerces-C Version? baust du die lib selber?
einer 3er Version, aber nicht die neueste. Hatte mit dem Build nur am
Rande zu tun, aber ein Jenkins Job buildet die ganzen Sourcen (Libs
weiss ich nicht)
> -hast du Valgrind und AdressSanitizer?
meines Wissens haben wir das nicht, sehr strikte Umgebung, muss ich mal
nachfragen; fkt. die unter AIX?
> -Kannst du auch unter Linux bauen (manche Entwickler machen das auch> Testgründen - vieleicht ist das bei euch auch so)?> -> damit könnte man eine viel breitere/besser Menge an Tools verwenden> -Arbeitest du in einer IDE oder alles mit make auf der Konsole?
Kollegen haben manchmal VisualStudio im Einsatz; ansonsten ich für Java
das Eclipse, und bauen tun wir über einen konfigurierten Jenkins Job,
der das make usw auslöst
>> 3. zum C++ Teil> -Kannst du den C++ Teil selbst bauen? hast du Zugriff auf> Kompile-Settings usw.?
ja
> -Kannst du den C++ Teil frei vom Tomcat laufen lassen und testen?
ja
> -Kannst du den C++ Teil einfach debuggen?
müsste ich wohl debuggable kompilieren, habe mit dem C++ Teil nur am
Rande zu tun.
Bin jetzt hauptsächlich Tomcat / Webservice Seite am tieferen
analysieren.
>> Jetzt wird zu jedem ? eine Antwort erwartet :)
Urlauber schrieb:> warum schreibst du nicht in C# oder Rust neu? XML ist doch trivial,> sollte nicht viel Aufwand sein.
laut ihm ein wenig Umfangreicher als NUR die SOAP Schnittstelle
>Historisch gewachsen, mehr als eine Dekade lang. Kern C++ Applikation>wohl sehr viele hunderttausende / Millionen (?) LOC.
und die werden mit C# auch nicht auf nichts zusammenschrumpfen
und die arbeiten ja an einer Neuentwicklung - die Ablösung des System
dauert aber noch eine Weile und zwischendurch muss das Produktivsystem
trotzdem laufen
>cppbert schrieb:>> Sind die Request/Response Pakete fixer grösse?>meines Wissens ja, prüfe ich aber nochmal.>> Wie viele verschiedene Request/Response Typen gibt es?>10 momentan.
d.h. du kannst die Kommunikation zur C++ App
auch direkt in der Tomcat App faken d.h. die Requests werden
direkt mit Dummy-Responses "in code" beantwortet =>
noch mehr Last möglich und kein Einfluss mehr durch C++
>cppbert schrieb:>> Männer werden>> auf dem Schlachtfeld geformt und nicht beim Kaffeekränzchen, mit dem>> schönen neuen Besteckt :)>Absolut! Meine Erfahrung in C, Programmierung von Leitsystemen: 3 Jahre>auf IBN ;-)
Super - anständige Posttraumatischen Belastungsstörung plus ordentliche
Narben im Nervengerüst zum Vorzeigen beim Veteranentreffen - ich bin der
schüchterne hinten Links :)
>> -Kannst du den C++ Teil frei vom Tomcat laufen lassen und testen?>ja
d.h. du gehst direkt mit dem SOAP Test Tool da dran?
>müsste ich wohl debuggable kompilieren,>habe mit dem C++ Teil nur am Rande zu tun.
Wenn du C++ testest solltest du sogar debuggable kompilieren - mehr
Symbole, mehr aufgeblähter Code usw.
cppbert schrieb:> Urlauber schrieb:>> warum schreibst du nicht in C# oder Rust neu? XML ist doch trivial,>> sollte nicht viel Aufwand sein.>> laut ihm ein wenig Umfangreicher als NUR die SOAP Schnittstelle
ganz genau, steckt mehr dahinter
> und die arbeiten ja an einer Neuentwicklung - die Ablösung des System> dauert aber noch eine Weile und zwischendurch muss das Produktivsystem> trotzdem laufen
absolut richtig!
cppbert schrieb:> d.h. du kannst die Kommunikation zur C++ App> auch direkt in der Tomcat App faken d.h. die Requests werden> direkt mit Dummy-Responses "in code" beantwortet =>> noch mehr Last möglich und kein Einfluss mehr durch C++
ich kann mit dem soap UI Tool Loadtests durchführen. Die simulieren
mehrere 100 Requests z.B. auf den Tomcat Server der wiederum mit der C++
XML Instanz kommuniziert und eine Response zurückbekommt.
Da habe ich wie gesagt, bereits 2 schwerwiegende Fehler gefunden:
- Heap der Webapp wächst stetig an nach mehreren Load-/Burst
Simulationen, der GC kann anscheinend nicht den allozierten RAM
freigeben. Es wurde nicht sauber implementiert, teilw. wurden Input- /
Outputstreamobjekte nicht wieder sauber geflusht / geclosed. Der
Hypothese nach teste ich nun soweit bis es beim initialisierten 512 MB
Heap Limit-Size crashen müsste
- Ich habe auch gesehen, dass das Error-Handling nicht korrekt
implementiert wurde, daher auch die "Read timed out", das ist ein
schwerwiegender Fehler. Das werde ich auch beheben, dann müsste die
Sache gegessen sein.
cppbert schrieb:> d.h. du gehst direkt mit dem SOAP Test Tool da dran?
wie vorher beschr.
cppbert schrieb:> Wenn du C++ testest solltest du sogar debuggable kompilieren - mehr> Symbole, mehr aufgeblähter Code usw.
ganz genau..
cppbert schrieb:> Super - anständige Posttraumatischen Belastungsstörung plus ordentliche> Narben im Nervengerüst zum Vorzeigen beim Veteranentreffen - ich bin der> schüchterne hinten Links :)
Ja, diese Symptome habe ich tragischerweise mitnehmen müssen, bin wohl
etwas komisch drauf ;-)
klausi schrieb:> Ja, diese Symptome habe ich tragischerweise mitnehmen müssen, bin wohl> etwas komisch drauf ;-)
ist mir direkt im 1. Post aufgefallen :-}
cppbert schrieb:> ist mir direkt im 1. Post aufgefallen :-}
Ach ja? O_O ohne Ironietags? Muss ich mir Sorgen machen? An was ist es
dir aufgefallen? ;-) zum Schluss wird hier ein Psychothread draus.. ;-)
klausi schrieb:> P.S.: wie vorher beschrieben benutze ich GC- Analyse Tools um die GC -> Logs der Webapp und den allozierten Heap zu analysieren.>> IBM>
z.B.https://www.ibm.com/support/pages/ibm-pattern-modeling-and-analysis-tool-java-garbage-collector-pmat> oder Eclipse MAT.. sehr hilfreich! https://www.eclipse.org/mat/
Wo wir gerade bei der Garbage Collection sind, spielt auch die
verwendete Version von Java eine große Rolle. Wie das bei Oracles und
IBMs Java-Implementierung ist, weiß ich nicht, aber mit dem OpenJDK hat
es zwischen Java8 und Java11 erhebliche Verbesserungen des GC gegeben,
sowohl was die Vermeidung von Memory Leaks angeht als auch was die
Laufzeit der Garbage Collection betrifft. Wenn Du also Memory Leaks oder
Timeouts im Tomcat siehst, kann es sinnvoll sein, mal eine aktuelle
Java-Version zu testen.
Wen es interessiert...
Den Fehler, die Root cause konnte ich nun eingrenzen, ist bestätigt und
ist wie folgt:
- Es ist ein fehlerhafter Service-Request an den Webservice (der
übrigens vor über 10 Jahren implementiert wurde) von einer
Drittapplikation, es wird ein Parameter zur Abfrage nicht mitübergeben,
sondern nur ganze Datumsbereiche (z.B. Zeitraum mehrere Tage), und das
seit ca. einem halben Jahr (der Request von der Drittapplikation wurde
dort aufgrund eines Changes entwickelt aber nicht sauber)
- Dies wurde auch nicht sauber geloggt, bzw. auf ersten Blick nicht
erkennbar (auch nicht im Debug-Log), jedoch wurde eine spezielle ID
eines Service geloggt, mit der konnten wir herausfinden, welche
Drittapplikation fehlerhafte Requests sendet
- Das implementierte Errorhandling ist fehlerhaft, der Webservice matcht
den fehlerhaften Request nicht mit der Error-Response die zurückgegeben
wird, daher wird der "Read timed out" Fehler produziert
- Dies mehrere hundert Male am Tag, jedoch treten auch "Read timed out"
Fehler in anderen Fällen auf, aber eher selten.
- Es traten früher Memory-Leak Probleme in der C++ XML Server Komponente
auf, heute nicht mehr.
- Java-Memory Leak: Ich konnte bei verschiedenen Loadtests des
Webservices ein Anwachsen des Heaps feststellen (JVM Limit 512 MB), OOM
Error ist aber bis heute in Produktion nicht aufgetreten
Ergo: der fehlerhafte Service Request in der Drittapplikation wird so
schnell wie möglich gefixt, und auch auf Webservice Seite hier wird das
Error-Handling optimiert, in Richtung "fail-safe".
Java Memory - Optimierungen werde ich auch durchführen (z.B. Output
Streams werden nicht sauber geflusht() oder geclosed () ).
C++ XML Server Komponente sieht (bis jetzt) gut aus.
Weitere Tests nach Implementierung und vor Deployment werden noch
durchgeführt.
Fazit/ Erkenntnisse besonders hier in Konzernsystemen:
- Code ist die beste Doku (nicht hinreichend dokumentiert)
- Alte Legacysysteme mit wenig oder nicht hinreichend gutem Logging
- Robustness: kein sauberes Errorhandling in jedem Fall (fehlerhafte
Service requests können eine Lücke reissen bzw. Performanceprobleme
verursachen)
- Teilw. schlampige bzw. "schnell-schnell" Implementierung ohne die
Kette bis ans Ende gedacht zu haben (Stichwort vernetztes Denken),
Auswirkungen berückichtigen, testen
- Abteilungen reden nicht miteinander (Silos)
klausi
klausi schrieb:> Fazit/ Erkenntnisse besonders hier in Konzernsystemen:
Alles in allem ein gut funktionierendes Unternehmen, besser macht es
kaum jemand.
Oliver
Und egal wie viel Unit-Tests existieren, wie hoch die Qualität des Codes
ist, saubere Abstraktionen und Modularität vorherrscht und der CI Server
testet bis zum abwinken, sobald die treibende Kraft dieser Qualitaet das
Team verlaesst weil andere Projekten mehr Zeit und Priorität
zugesprochen wird kann die beste Software in den Händen von weniger
Erfahrenen problemlos in kürzester Zeit verotten wie es sich keiner der
Erschaffer je hat vorstellen können, die Hoffnung ist nur das es langsam
passiert oder keine neuen Anforderungen kommen
cppbert schrieb:> Und egal wie viel Unit-Tests existieren, wie hoch die Qualität des Codes> ist, saubere Abstraktionen und Modularität vorherrscht und der CI Server> testet bis zum abwinken, sobald die treibende Kraft dieser Qualitaet das> Team verlaesst weil andere Projekten mehr Zeit und Priorität> zugesprochen wird kann die beste Software in den Händen von weniger> Erfahrenen problemlos in kürzester Zeit verotten wie es sich keiner der> Erschaffer je hat vorstellen können, die Hoffnung ist nur das es langsam> passiert oder keine neuen Anforderungen kommen
Das unterschreibe ich zu 101%, bin auch in so einem Software-Großprojekt
unterwegs mit goldenen Inseln und stinkenden Jauchegruben.
Bei uns haben es die sogenannten "Feature-Teams" (temporär gegründete
Querschnittsteams die zügig Funktionalität entwickeln soll(t)en)
geschafft eine ganze Reihe an gut getesteten und dokumentierten
Komponenten unwiederbringlich in die Bug-Hölle zu befördern. Jetzt ist
man nur noch mit Feuer löschen beschäftigt :-) Das wird in den nächsten
1-2 Jahren ein schönes Schlachtfest geben wie damals vor knapp 20
Jahren, als das Mittelmanagement die Hosen runterlassen musste als das
Missmanagement nicht mehr kaschiert werden konnte und Top-Level die
Sense ausgepackt hat und alles was auf sonstwie -leiter geendet hat,
wegrasiert wurde. War ein Höllenritt damals, wie ein reinigendes
Gewitter, aber danach konnte man wirklich sehr angenehm arbeiten bis zu
den letzten 3-4 Jahren als es wieder anfing, dass die Dichte an -leitern
nun wieder zunimmt. Nun gut, ich sehs gelassen, meine Schäfchen sind
anders als damals (da hatte ich frisch gebaut mit Mitte 30 und echte
Existenzsorgen) im Trockenen und muss mich davon nicht mehr stressen
lassen. Konzerne sind schon eigene Mikrokosmen diesbezüglich.
Tja und bevor man kaputte Libs, GC usw vermutet sollte man mal auf den
Nachrichtenflow schauen. Da haben wir es wieder Parameter war falsch.
Ich weiss ja nicht wie das in XML/SOAP ist aber gibts da kein Gemecker
bei falschen Parametern? Da kann man doch glaube ich auch Typen
vorgeben,....
cppbert schrieb:> Deine Taskforce war also erfolgreich und ist jetzt dabei die> Geister der> Vergangenheit zu vertreiben - Glückwunsch!
Vielen Dank! ja ich analysiere gerne komplizierte Probleme, lieber aber
im eigenen Code ;-)
Den C++ Teil werde ich mir trotzdem nochmal ansehen, da gabs früher mal
Memory Leaks, nicht mehr heute, ist aber extern entwickelt,
das Java / Webservice Zeugs wurde inhouse entwickelt, da aber keine mehr
da (1 kenn ich noch in anderer Abteilung); da werde ich noch
Optimierungen auch bezgl. GC vornehmen.
Lerne immer gerne täglich, dazu, ausgelernt.. hat man nie..
Oliver S. schrieb:> klausi schrieb:>> Fazit/ Erkenntnisse besonders hier in Konzernsystemen:>> Alles in allem ein gut funktionierendes Unternehmen, besser macht es> kaum jemand.>> Oliver
Hmmm.. kann sein.. evtl. die grossen? Wirklich Tech-Unternehmen? Amazon,
Google?
cppbert schrieb:> kann die beste Software in den Händen von weniger> Erfahrenen problemlos in kürzester Zeit verotten wie es sich keiner der> Erschaffer je hat vorstellen können, die Hoffnung ist nur das es langsam> passiert oder keine neuen Anforderungen kommen
tja.. schade drum
besser man entwickelt als Hobby.. nicht mehr im Beruf..
Ex-Boygroupmember schrieb:> Da haben wir es wieder Parameter war falsch.> Ich weiss ja nicht wie das in XML/SOAP ist aber gibts da kein Gemecker> bei falschen Parametern? Da kann man doch glaube ich auch Typen> vorgeben,....
Nein, Es wurde gar kein Parameter übergeben, wo aber einer übergeben
werden müsste.
Das Error-Handling und Logging wurde nicht sauber implementiert. Statt
einer sauberen Exception nach z.B. 20ms gab es einen "Read-Timed-out
Fehler" nach 7s, bei jedem solcher Requests, das waren hunderte pro Tag
von einer Drittapplikation (das man zuerst auch nicht erkannte, woher
der Request kam, kein sauberes Logging).
Trotzdem gibt es noch Optimierungspotential im Java Teil (GC), sauberes
Schliessen von Outputstreams usw.