Störungen bei der Citavi-Cloud im November 2019 - Die Hintergründe

Peter M. hinzugefügt 9 Monaten her

Wenn Sie im November 2019 mit einem Cloud-Projekt gearbeitet hatten, wird Ihnen das vielleicht aufgefallen sein: Mehrmals täglich meldete Citavi, es bestehe keine Verbindung zur Cloud. Die Seite http://status.citavi.com meldete aber, dass alle Systeme fehlerfrei liefen. Wir erklären, wie es zu den Problemen gekommen ist und was wir dagegen unternommen haben.

Wissenswertes zur Architektur von Citavi

Seit der Version 6 von Citavi können Projekte in drei verschiedenen Datenbanken gespeichert werden: «Lokal» in einer SQLite-Datenbankdatei, auf einem SQL-Server (für Unternehmen und Organisationen) sowie in der Citavi-Cloud.

Bei allen Varianten ist es möglich, mit mehreren Anwendern gleichzeitig an einem Projekt zu arbeiten. In der Cloud ist diese Möglichkeit besonders einfach, weil die User nicht mit dem gleichen Netzlaufwerk bzw. dem gleichen Datenbankserver verbunden sein müssen.

Die gleichzeitige Arbeit an einem Projekt ist technisch relativ anspruchsvoll. Der Citavi-Desktopclient (das Programm, welches auf dem Windows-Rechner der Anwender ausgeführt wird) muss laufend ermitteln, welche Änderungen andere User in das Projekt geschrieben haben; diese müssen im Betrieb mit den eigenen Änderungen synchronisiert werden.

Im Cloud-Betrieb ist diese Anforderung besonders hoch. Damit die Server nicht überlastet werden, verbietet es sich, dass alle Citavi-Clients die Server permanent nach Änderungen fragen. Stattdessen baut der Server eine «stehende» Verbindung zu jedem einzelnen Client auf. Wenn User B Änderungen an einem Projekt vornimmt, schickt der Server über diese Verbindung eine Nachricht an den Citavi-Client von User A. Dieser holt dann die neuesten Daten ab und integriert sie in seinen Arbeitsspeicher.

Ein notwendiges Update

Als wir den Server-Code der Citavi-Cloud entwickelt haben, war «ASP.NET» der Stand der Technik. Die Microsoft-Technologie zum Aufbau stehender Server-Client-Verbindungen nannte sich «SignalR for ASP.NET».

Mittlerweile hat Microsoft seine Server-Technik weiterentwickelt. «State of the Art» ist jetzt «ASP.NET Core». Wir haben unsere Server im Laufe des Novembers darauf umgestellt. Zusammen mit «ASP.NET Core» erschien auch eine neue Version von SignalR: «SignalR for ASP.NET Core».

Zwang zur Rückwärtskompatibilität

Leider ist die «Core»-Version von SignalR nicht rückwärtskompatibel mit der älteren Version. Damit die bestehenden Citavi-Clients (Versionen 6.0 bis 6.3) weiter funktionieren, mussten wir einen «SignalR Redirector» entwickeln, der die Kompatibilität mit diesen Clients wahrt.

Dieser Redirector hat in den letzten Wochen massive Probleme verursacht, welche sich bei unseren Anwendern in häufigen Störungen der Cloud-Verbindung bemerkbar gemacht haben.

Ein Phänomen, viele Ursachen

Die Probleme bei dem SignalR Redirector äußerten sich in so genannten Bursts, das heißt einem plötzlichen, massiven Anstieg der Serverlast. Wir haben jeweils am frühen Morgen neue Versionen eingespielt und die Server beobachtet. Zu diesem Zeitpunkt lief alles störungsfrei.

Gegen 9:30 Uhr MEZ, als eine nennenswerte Anzahl von Citavi-Usern mit Cloud-Projekten arbeitete, kam es zu einer plötzlichen Vertausendfachung der Server-Client-Verbindungen.

Diese Explosion ging mit Sicherheit nicht auf tatsächliches User-Verhalten zurück, sondern war eine technische Fehlfunktion. Es war anspruchsvoll, die Ursache zu ermitteln und zu beseitigen – besonders auch deshalb, weil es sich nicht um eine einzige Ursache, sondern um eine komplexe Verkettung von Gründen handelte, die wir in unseren eigenen funktionalen und Load Tests nicht nachstellen konnten.

  • Die ältesten Citavi-Clients (Versionen 6.0 und 6.1) enthalten von unserer Seite eine fehlerhafte Logik, die zu häufigen Reconnects führt. Dieser Fehler ist zwar seit Citavi 6.2 behoben, aber es gibt Kunden, welche die noch älteren Versionen einsetzen.
    In einem ersten Schritt haben wir die Reconnects dieser Clients serverseitig geblockt bzw. ausgebremst.
  • Parallel dazu haben wir die Anzahl und die Leistung unserer Server massiv erhöht, auf bis zu 10 Server mit hoher Performance.
  • Beide Maßnahmen brachten nicht die erhoffte Zuverlässigkeit. Wir mussten feststellen, dass eine Verschlüsselung, die wir im Zusammenhang mit der Lastverteilung auf die 10 Server eingesetzt hatten, zu viel CPU-Last verursachte. Wir haben daraufhin ein anderes Verschlüsselungsverfahren eingesetzt, welches dieses Problem behob. Dennoch traten die Bursts noch immer auf.
  • Nach zahlreichen weiteren Maßnahmen stießen wir auf eine Stelle im Quellcode der SignalR-Bibliothek von Microsoft, welche wir mittlerweile für die Hauptursache des Problems halten. SignalR schickt darin in einem «For Each»-Loop jede Sekunde eine «Keep Alive»-Nachricht an alle Clients. Die Clients sind standardmäßig so konfiguriert, dass sie mindestens alle zwei Sekunden eine Keep-Alive-Nachricht erwarten. Falls sie diese nicht erhalten, führen sie einen Reconnect aus.
    Ab einer gewissen Last dauerte die Ausführung des erwähnten Keep-Alive-Loops mehr als 2 Sekunden; die Clients versuchten deshalb, sich neu zu verbinden – was mehr Last auf den Servern verursachte; der Keep-Alive-Loop dauerte damit noch länger; die Clients erhielten noch immer kein Signal und verbanden sich erneut – und so weiter und so fort, bis zum CPU- und Memory-Tod aller Server.

In der neueren «ASP.NET Core»-Bibliothek hat Microsoft dieses Keep-Alive-Verfahren geändert. Wie oben erwähnt, müssen wir jedoch auch die alte Bibliothek einsetzen, um kompatibel mit älteren Citavi-Clients zu sein.

Lösung gefunden

Wir haben nun eine Möglichkeit gefunden, den Clients bei der initialen Verbindung einen Konfigurationsparameter zu senden, damit sie nicht mehr alle zwei Sekunden ein Keep-Alive-Signal erwarten. Um alle Clients (auch solche auf Notebooks im Ruhezustand) zu einem Verbindungsabbruch und damit zum Einlesen dieser Konfiguration zu zwingen, haben wir die SignalR-Server zwei Mal für ca. 10 Minuten ausgeschaltet.

Die verschiedenen Maßnahmen und diese Neustarts haben Wirkung gezeigt. Seit dem 6. Dezember 2019 funktioniert die Kommunikation völlig stabil.

Welche Lehren ziehen wir aus dem Vorfall?

1) Ein technisches Problem, das mehrere parallele Ursachen hat, ist immer schwer zu lösen. Wir sagen das zur Erläuterung und nicht, um uns damit zu entschuldigen.

2) In ähnlichem Sinne ist es schwierig, Konsequenzen aus den Problemen innerhalb des SignalR-Codes von Microsoft zu ziehen. Es ist in der heutigen Software-Entwicklung unverzichtbar, Funktionsbibliotheken von Drittherstellern einzusetzen. Wir müssen dabei – wie alle anderen Software-Hersteller auch – auf die Zuverlässigkeit dieser Bibliotheken vertrauen. (Aus diesem Grunde setzen wir nur Bibliotheken von etablierten und renommierten Herstellern ein.)

Problematisch im aktuellen Fall war, dass Microsoft zwar bereits eine neue Version mit einem besseren Verhalten entwickelt hatte, wir diese aber aus Kompatibilitätsgründen nicht einsetzen konnten. Diese Situation wird sich auch in Zukunft für Citavi nicht grundlegend ändern; selbstverständlich werden wir unsere Server immer dem neuesten Stand der Technik anpassen, und ebenso selbstverständlich werden wir darauf achten, dass ältere Citavi-Clients kompatibel bleiben.
Auf der positiven Seite steht, dass Microsoft das gesamte .NET Framework Open Source gestellt hat. Dies erlaubte uns, den Source Code von SignalR zu analysieren und die problematische Loop-Methode zu identifizieren.

3) Wir haben bereits heute umfangreiche Testverfahren:

  • Jede Nacht wird der neueste Code von weite über 1.000 programmgesteuerten Unit Tests kontrolliert.
  • Jede Nacht läuft eine umfangreiche Suite von programmgesteuerten Tests, welche das User Interface «durchklickt» und kontrolliert.
  • Ebenfalls jede Nacht laufen Load Tests, welche nicht die Funktionalität des Codes prüfen, sondern sein Verhalten unter Last.

Diese Load Tests haben im vorliegenden Falle offensichtlich zu wenig genau das Verhalten der verschiedenen älteren Versionen von Citavi simuliert; andernfalls hätten wir die Probleme bereits dort erkennen und beheben können und nicht erst in der produktiven Umgebung. Hier werden wir Verbesserungen vornehmen.

4) Bisher gibt es bei der Aktualisierung unserer Server einen «harten» Wechsel: Der Datenverkehr wird innerhalb kurzer Zeit von der älteren Codeversion auf die neuere Codeversion umgeleitet.

Wir arbeiten an einem sanfteren Verfahren, bei dem zunächst nicht der gesamte Datenverkehr umgeleitet wird, sondern nur ein Teil. Damit können wir neuen Code unter 10%, 20%, 50% und schließlich 100% des realen Datenverkehrs testen.

5) Azure, die Cloud von Microsoft, welche wir nutzen, ist eine sehr hochentwickelte und konkurrenzfähige Plattform – dies zeigt sich auch in ihrem stetig wachsenden Marktanteil. Die SignalR-Technologie bildet dabei jedoch einen Ausreißer.

Wir werden in Citavi Clients ab der Version 6.4 zu einem anderen Anbieter von «Real Time»-Kommunikation wechseln, der erfolgreich große Internetdienste und Konzerne hostet.

Zusammengefasst

Zu keinem Zeitpunkt fielen die eigentlichen Citavi-Server oder gar die Datenbanken aus. Es handelte sich um eine Kommunikationsstörung zwischen Servern und Clients. Wir sind uns aber bewusst, wie schwerwiegend die Störungen für unsere Kundinnen und Kunden waren und bitten dafür um Entschuldigung.

Diese Diskussion wurde geschlossen. Bitte erstellen Sie bei Bedarf einen neuen Beitrag.