Wochenbericht für die erste Woche im März 2023

In letzter Zeit haben sich die Anforderungen an die Einhaltung von Vorschriften immer mehr in die technische Seite der Dinge eingeschlichen. In letzter Zeit kommen immer wieder Produkte auf den Tisch, bei denen es um die Umsetzung dieser und jener Compliance-Anforderungen geht. Oder sie führen eine Art Compliance-Fragebogen aus. Meiner Meinung nach geht es bei der Einhaltung der Vorschriften vor allem um die Speicherung von Benutzerdaten. Der Zugriff muss standardisiert werden, und dann können die Benutzer allmählich anfangen, ihre eigenen Daten zu kontrollieren. Dann gibt es auch einige personelle und organisatorische Veränderungen, die sich auf die technische Ebene auswirken. Zum Beispiel wurde ein Geschäftsbereich in andere Abteilungen verlagert, und wir haben dann Ressourcen wie Datenbanken mit diesem Geschäftsbereich geteilt. Hier tritt die Kostenfrage in den Vordergrund, d.h. das Geld sollte dort gezählt werden. Es handelt sich zwar um ein Unternehmen, eine Unternehmensgruppe, aber ich habe das Gefühl, dass es an den internen Buchhaltungsmechanismen des Unternehmens liegen könnte, denn diese Kostenfragen sind immer noch schwerwiegender, werden immer argumentieren, was: sie nutzen unsere Datenbank, das Geld ist immer noch auf unserer Seite und so weiter. Manchmal habe ich das Gefühl, dass es sich dabei um internen Verbrauch handelt, nicht um eine Entwicklungsperspektive. Hinzu kommt, dass andere Unternehmen möglicherweise einige gemeinsame Datenbankstrukturen oder Schnittstellen aufgrund von Bedarfsanpassungen ändern müssen, was noch problematischer ist. Denn derzeit erhalten wir keine Anerkennung für die Arbeitsstunden, die sie für diese Dinge aufwenden. Allerdings werden wir jeden Tag von den Leuten dort gehetzt und bombardiert. Es ist noch schwieriger, wenn man in der Mitte gefangen ist. Die Migration des PHP-Gateways, die ich in meinem letzten Wochenbericht erwähnt habe, war in den ersten ein oder zwei Monaten tatsächlich in Arbeit. Tatsächlich wurde er schon vor langer Zeit geschrieben, aber bei der anschließenden Umstellung des Datenverkehrs auf den neuen Dienst traten immer wieder solche und solche Probleme auf. Eine Besonderheit ist, dass in der Testumgebung lange Zeit niemand zu finden war, während in der offiziellen Umgebung immer eine Person zu finden war. Diese Schnittstelle kann plötzlich nicht mehr verwendet werden, die Schnittstelle meldet plötzlich Fehler und so weiter. In diesem Fall, weil das Problem auf der Leitung auftritt, können Sie nur zuerst den Verkehr zurückfahren und dann das Problem analysieren. Nach zwei Durchgängen wird eine Woche vergehen. Manchmal dauert es 4 oder 5 Tage, bis jemand das Problem findet. Ein solcher Prozess dauert sogar noch länger. Der Leiter sagt zwar, dass dies schon lange so gemacht wird, aber die tatsächliche Situation ist so. Obwohl die anschließende spezifische Code-Schreib- und Wartungsarbeit des Dienstes nicht meine Aufgabe ist, aber ich weiß auch, dass ein neuer Dienst, der den bestehenden Dienst vollständig ersetzen soll, einen Prozess haben muss. Denn in Ermangelung von Dokumentation und Testfällen wissen Sie nicht, welche versteckten Mechanismen eine Schnittstelle hat, und es ist nicht ganz klar, ob der von mir geschriebene Code dem Original entspricht. Auf der Implementierungsebene wurden also viele Dinge nicht explizit gemeldet, aber ich war der Meinung, dass das Management auch in der Lage sein sollte, dies zu verstehen. Obwohl der Prozess ziemlich iterativ und schwierig war, wurde das Refactoring dieses Dienstes schließlich in dieser Woche abgeschlossen und der gesamte Datenverkehr wurde auf den neuen Dienst migriert. Das heißt, der Lebenszyklus dieses alten PHP-Gateways ist vorbei. Ich habe das Hauptgeschäft im Backend-Bereich jetzt fast ein halbes Jahr lang übernommen, und jetzt wird mir klar, dass ich bei meiner ersten Übernahme aufgrund mangelnder Erfahrung immer das Gefühl hatte, dass die Technologie anderer Leute undurchschaubar ist. Nach einer langen Zeit des Kontakts weiß ich jedoch, dass sie so und so viele Unzulänglichkeiten aufweist. Es gibt auch einige Designfehler, die sehr schwerwiegend sind. Zum Beispiel die Verwendung von Redis als Datenbank. Um es ganz offen zu sagen, es gibt keine festgelegte Ablaufzeit für den Cache, so dass die Daten in Redis nicht verloren gehen können. Es gibt auch einige alte Dienste, für die es keine Dokumentation mehr gibt und die schon lange nicht mehr gewartet werden, so dass es im Grunde unmöglich ist, sie genau zu untersuchen. Es gibt jedoch immer ein oder zwei dieser Dienste, auf die noch zugegriffen wird oder die schon lange nicht mehr zugänglich sind, und die Kunden entdecken sie plötzlich in den letzten Tagen und drängen uns, sie zu lösen. Viele Sicherheitsprobleme müssen ebenfalls behoben werden, eine bestimmte Anzahl von API-Konten hat eine hohe Anzahl von Berechtigungen, die angeglichen werden müssen, aber ich weiß nicht, was diese verschiedenen Konten genau tun. Diese Probleme treten einfach täglich auf, und es ist schwer, sie zu vermeiden. ...

November 15, 2023

Wöchentlicher technischer Bericht für die vierte Woche im Februar 2023

Diese Woche ist mir aufgefallen, dass einige der Service-Frameworks nicht sehr gut geschrieben sind, insbesondere bestimmte Java-Frameworks. Wenn die CPU-Auslastung etwa 40% erreicht, kommt es zu vielen Timeouts. Bei diesen Diensten reichen die CPU-Kerne und die Speicherkapazität nicht aus, die Anzahl der arbeitenden Threads ist nicht hoch genug. Es ist jedoch nicht genug, um die CPU laufen zu lassen. Mit Hilfe von Java-Performance-Tools zur Analyse der Entdeckung, in der Tat, festgestellt, dass die meisten der Arbeits-Threads in der Idel oder Waiting Status. Derzeit ist die umfassende Analyse aller Umstände, noch rätselhaft. NIO auch verwendet, auch die Netty Rahmen verwendet, aber der Durchsatz ist nicht nach oben. Bei der Analyse der Threads wurde festgestellt, dass es keine besonders beschäftigten Business-Threads gibt. Es wird angenommen, dass IO oder eine Art von Wartemechanismus zu dieser geringen Verarbeitungseffizienz führt. Diesmal wollte ich die Kosten senken, indem ich die Anzahl der Knoten verringerte, und ich habe vor der Ausführung nicht besonders viele Faktoren berücksichtigt. Wenn ich also die Knotenkapazität reduziere, prüfe ich nur die CPU-Auslastung, um zu beurteilen, ob der Knoten dies verkraften kann oder nicht. Als ich die durchschnittliche CPU-Auslastung der Arbeitslast in der Region Peking auf 35%-40% erhöhte, kam es beim gesamten Dienst zu einer großen Anzahl von Timeouts. Zu diesem Zeitpunkt war ich schockiert. Als ich es später auf dem Monitor analysierte, waren fast alle Knoten in der Hintergrundumgebung ausgefallen, das heißt, sie befanden sich in einem “Schockzustand”. In dieser Woche habe ich auch die Umstrukturierung eines alten PHP-Gateway-Dienstes fortgesetzt, und das neue Gateway ist in Java geschrieben. Aber ich bin nicht wirklich dafür, Java als Gateway zu verwenden, denn die Ausführungseigenschaften der Java-Sprache bestimmen weitgehend, dass sie nicht für besonders hohe Gleichzeitigkeit geeignet ist. Und wir verwenden derzeit JDK 8 und haben keine leichtgewichtigen Threads eingeführt, jeder 4c8g-Container hat bis zu 800 Threads, der Overhead für das Umschalten von Threads ist besonders groß. Der Durchsatz eines einzelnen Containers ist also begrenzt, für die gleiche Menge an Datenverkehr sind mehrere Container erforderlich. Zunächst wurde ich in Go umgeschrieben, dieses Framework ist sehr gut und hat auch ein eigenes Team zur Pflege, aber der Leiter ließ mich trotzdem die Abteilung für selbstentwickelte Java-Frameworks benutzen. Vielleicht sind es vor allem personelle Erwägungen, aber ich habe keine andere Wahl, als es zuerst zu schreiben. ...

November 15, 2023

Technischer Wochenbericht für die dritte Woche im Februar 2023

Diese Woche haben wir uns mit einem Risiko befasst, das vor den Feiertagen entdeckt wurde. Ein Dienst, der Redis verwendete und keine TTL für den Schlüssel einstellte, sondern sich auf die Redis-Eliminierungsrichtlinie verließ. Ich sehe, dass dieser Dienst Redis mit einer LRU-Eliminierungsstrategie verwendet. Diese Strategie scheint perfekt zu sein, aber es gibt Fallstricke, wenn über einen bestimmten kürzeren Zeitraum viel Schreibverkehr stattfindet. Dann löst Redis den Eliminierungsprozess aus und gibt sein Bestes, um genügend Speicherplatz freizugeben. Das bedeutet, dass Redis normale Operationen wie Abfragen nicht mehr sehr gut ausführen kann. Dies führt zu dramatischen Schwankungen bei der Lese- und Schreiblatenz für Redis aus der Geschäftsschicht. Ich hatte dieses Problem bisher 2 Mal. Außerdem ist Redis ohne die Einstellung von TTL immer zu 100% ausgelastet, und wir können anhand der Kapazität nicht erkennen, wie viel gekaufte Kapazität für das aktuelle Geschäftsvolumen ausreicht. Es ist auch ungewiss, ob die Kosten durch eine Verringerung der Kapazität in den Zeiten geringerer Auslastung gesenkt werden können. Daher ist es sehr wichtig, ausreichend freien Platz für Redis zu lassen. Daher muss ich den Dienst so ändern, dass für jeden neu geschriebenen Schlüssel eine TTL gesetzt wird. Nach der Logik von Redis wird auch eine TTL gesetzt, wenn der Schlüssel zum Zeitpunkt des Schreibens bereits existiert. Im Interesse der Stabilität des Geschäfts möchte ich nicht, dass für alle Schlüssel eine TTL gesetzt wird. Ich habe diese Option tatsächlich erforscht und die Notwendigkeit eines Cursors beim Traversieren genutzt. Die Länge des TTL-Satzes ist ebenfalls heikel. Um zu verhindern, dass eine große Anzahl von Schlüsseln gleichzeitig abläuft, was zu großen Schwankungen in der Latenzzeit führt, setzen Sie die TTL auf die Basisdauer der Zeit, nachdem Sie eine zufällige Länge hinzugefügt haben. Angenommen, die Basisdauer ist T, dann liegt die Länge der TTL nach Hinzufügen der Zufallsdauer zwischen T und 2T. Das bedeutet, je länger der Schlüssel bleiben muss, desto breiter ist die Verteilung des Ablaufs. Dies sorgt für eine gleichmäßigere Geschäftslatenz und verhindert eine Überlastung der Datenbank. ...

Juni 21, 2023

Technischer Wochenbericht für die zweite Woche im Februar 2023

Von Ende Januar bis Anfang Februar fällt es unter das chinesische Neujahrsfest. Während dieser Zeit muss die Person, die für die Sicherstellung des Betriebs der chinesischen Neujahrsphase verantwortlich ist, in Bereitschaft sein, um sich um Online-Probleme zu kümmern. Ich war in ständiger Sorge, und das Gute daran ist, dass die Online-Probleme nicht aktiv zu mir kamen. Am besten ist es, während des chinesischen Neujahrsfestes insgesamt unbeweglich zu bleiben. Diese Woche bewerte ich die Auswirkungen einer wichtigen Anforderung. Ich bin der Meinung, dass bei einer neuen Geschäftsanforderung, insbesondere wenn sie sich auf ein komplexes Geschäftssystem bezieht, mehrere Auswirkungen berücksichtigt werden müssen. Wenn man zu diesem Zeitpunkt noch nicht besonders vertraut und erfahren mit dem System ist, ist es am besten, nur minimale Änderungen vorzunehmen. Es geht nicht darum, konservativ zu sein, sondern darum, die Auswirkungen so gering wie möglich zu halten. Denn Sie wissen nicht, wo ein kontra-intuitiver Mechanismus wichtige Geschäftslogik ausführt. Zu dieser Schlussfolgerung bin ich nicht zufällig gekommen. Dieser Beitrag wurde sechs Monate später geschrieben, und als ich ihn schrieb, war ich bereits mindestens zweimal auf dieses Problem gestoßen. Damals nahm ich eine drastische Änderung an einem Dienst vor, und als die Änderung durchgeführt wurde, war alles in Ordnung. Auch nach der Veröffentlichung schien es normal zu sein. Erst einige Wochen später stolperte ich über einen Mechanismus, der vor- und nachgelagert war, und er wurde fast von mir beeinflusst. Wenn Sie ein Geschäftssystem übernehmen, ist die Wahrscheinlichkeit groß, dass es übertragen wird und viele Hände, die eine Menge Geschichte verbergen, die Sie nicht kennen, so dass der Rahmen, die Kernlogik sich nicht bewegen kann, solange sie sich nicht bewegt. Dann, diese Woche vollständig gelöst das Problem gegen eine Sicherheit Verschlüsselungsdienst Verschlüsselung Schnittstelle ist nicht kompatibel mit Chinesisch. Das Hauptproblem ist, dass der ursprüngliche Text direkt als Redis-Schlüssel verschlüsselt wird. Wenn der ursprüngliche Text auf Chinesisch vorliegt, werden Sie feststellen, dass der Schlüssel zwar gespeichert ist, aber nicht gefunden werden kann. Meine Lösung ist, dass der Inhalt des Schlüssels beim Speichern nicht direkt einen geschäftlichen Originaltext enthalten sollte, sondern zuerst den Hashwert. Dadurch lassen sich einige Kodierungs- und Kompatibilitätsprobleme vermeiden, aber auch die Sicherheit kann erheblich verbessert werden. ...

Juni 21, 2023

Technischer Wochenbericht für die zweite Woche im Januar 2023

Diese Woche ging es hauptsächlich darum, die Stabilität verschiedener Dienste im Vorfeld des chinesischen Neujahrsfestes sicherzustellen. Kürzlich stellte ich fest, dass ein bestimmter Dienst während der Hauptverkehrszeiten häufig Zeitüberschreitungen meldete, und ich erinnerte den Eigentümer des Dienstes daran, sich darum zu kümmern. Aber nach ein paar Tagen konnte der Eigentümer des Dienstes den Grund immer noch nicht erklären. Ich musste mich persönlich um das Problem kümmern, denn der Alarm war sehr ernst, und die Timeout-Rate einiger Knoten erreichte bis zu 20%. In diesem Zeitraum dürfte es an den bevorstehenden Feiertagen liegen, der Datenverkehr ist deutlich gestiegen, im Vergleich zu Ende Dezember um 100%. Es besteht also zunächst der Verdacht, dass die Übertragungskapazität des Dienstes unzureichend ist, also wurde zunächst eine Kapazitätserweiterung durchgeführt. Die Erweiterung löste das Problem jedoch nicht, und die Alarmhäufigkeit und die Timeout-Rate blieben im Wesentlichen unverändert. In diesem Fall wurde nach einer Analyse des Quellcodes des Dienstes festgestellt, dass die Schnittstelle des Dienstes zunächst einen nachgelagerten Dienst aufruft und dann asynchron Daten in die Datenbank einfügt. Da der asynchrone Vorgang den Worker-Thread nicht blockiert, liegt der Verdacht zunächst auf diesem nachgelagerten Aufruf (tatsächlich habe ich mich lange mit der Datenbankseite herumgeschlagen). Ich meldete mich vom Terminal aus bei einem Knoten an, um die Protokolle zu prüfen, und stellte fest, dass alle nachgelagerten Aufrufe tatsächlich an dieselbe IP und denselben Port gingen und an den Scarecrow-Knoten gerichtet waren. Also führte ich zunächst eine Up-Cloud-Operation für diesen Dienst durch, um die Auswirkungen des Verlusts der Scarecrow-Weiterleitung auszuschließen. Nach der Fertigstellung der Cloud stellte ich fest, dass in einer bestimmten geografischen Region (nicht der ursprünglichen geografischen Region) eine große Anzahl von Timeouts auftrat, die auch nach der Erweiterung nicht behoben werden konnten, was mich sehr verwunderte. Ich war sehr neugierig, warum die Timeout-Rate nach dem Wechsel in die Cloud höher wurde. Nachdem ich das Problem von der Cloud aus überwacht und analysiert hatte, stellte ich fest, dass nach der Drosselung des Datenverkehrs einer der nachgelagerten Knoten des Dienstes in der Cloud eine sehr hohe CPU-Auslastung hatte, während die anderen eine sehr niedrige hatten. Ich vermutete ein Lastausgleichsproblem und ging zurück, um den Quellcode des Dienstes zu überprüfen. Nachdem der Dienst die Liste der verfügbaren Knoten für den nachgelagerten Dienst aus der Registrierung abgerufen hatte, rief er nur den ersten Punkt in der Liste auf. So konzentriert sich fast der gesamte Verkehr aus einer bestimmten geografischen Region auf einen der Knoten des nachgelagerten Dienstes. Und wenn er ursprünglich über Scarecrow weitergeleitet wurde, nimmt Scarecrow einen Lastausgleich vor, wenn es den Knoten in der Cloud aufruft. Das anfängliche Problem bestand also darin, dass der Datenverkehr stark anstieg und der Dienst keinen Lastausgleich hatte, so dass eine der Scarecrows überlastet wurde, was wiederum zu einer Zeitüberschreitung führte. Bei den Scarecrows handelt es sich um Proxy-Knoten, die keine eigene Logik haben, so dass die Anzahl der Konkurrenzen, die sie verarbeiten können, viel größer ist und das Timeout-Problem nicht sehr auffällig ist. In der Cloud konzentriert sich der Datenverkehr direkt auf einen Business Node. Eine große Anzahl von Datenverkehrsströmen führt sofort zu einer großen Anzahl von Timeouts bei den Business Nodes. Mit der obigen Behauptung, gehen Sie zurück, um die Überwachung der Vogelscheuche zu finden, und festgestellt, dass eine Vogelscheuche in der Tat überlastet wurde, CPU-Auslastung tatsächlich mehr als 95 erreicht. Da wir die Ursache kennen, ist der nächste Schritt, zur Cloud zu gehen, um zunächst die Eliminierung von Timeout-Alarmen zu maximieren und dann den Code zu ändern, um einen Algorithmus für den zufälligen Lastausgleich hinzuzufügen. Dies geschah, weil eine Änderung des Codes vor dem Urlaub verfahrenstechnisch mühsamer gewesen wäre. Also verdoppelte ich zunächst die Anzahl der Kerne eines einzelnen Knotens des nachgelagerten Dienstes, was die Verarbeitungskapazität stark erhöht. Als ich dann den Datenverkehr reduzierte, stieg die CPU-Auslastung eines nachgelagerten Knotens plötzlich an und blieb schließlich in einem viel höheren Verhältnis als die der anderen Knoten, was ja auch zu erwarten war. Als sich der gesamte Dienst beruhigt hatte, war der Upload in die Cloud erfolgreich, und zu diesem Zeitpunkt waren die Alarme beseitigt und die Timeout-Rate auf Null gesunken. Der nächste Schritt besteht darin, den Code des geänderten Dienstes zu modifizieren, den Lastausgleichsmechanismus hinzuzufügen und eine neue Codeversion für den Dienst zu veröffentlichen, nachdem die verschiedenen Prozesse genehmigt wurden. Nachdem ich die neue Version freigegeben hatte, war die CPU-Auslastung jedes Knotens des nachgelagerten Dienstes nahe und das Problem war endlich gelöst. ...

Februar 14, 2023

Wöchentlicher technischer Bericht für die erste Woche im Januar 2023

Auf dem Weg ins Jahr 2023 wird dieses Jahr ein schwieriges Jahr werden. In diesem Jahr stehen mehrere Herausforderungen an. Eine davon ist die Migration aller Daten, die bisher auf physischen Servern bereitgestellt wurden, in die Cloud. Dann ist da noch die beschleunigte Entwicklung einiger neuer Mitarbeiter im Team, damit sie so schnell wie möglich die Dienste übernehmen können, die derzeit Teil des Hauptgeschäfts sind, und die in der Lage sein müssen, eigenständig Benutzerprobleme zu lösen und die Dienste zu optimieren. Dadurch kann ich einen Teil der Arbeit auf sie übertragen und mich auf wichtige Ziele konzentrieren, die in diesem Jahr voraussichtlich viel Zeit in Anspruch nehmen werden. Hinzu kommt, dass ich eine Phase des persönlichen Lernens in technischen und anderen Bereichen erreicht habe, die die Richtung meines Lebens in den nächsten 7-8 Jahren bestimmen wird. In dieser Woche lag mein Hauptaugenmerk auf dem Entwurf und der Spezifikation des Logging-Frameworks und der Protokollverfolgung für mehrere Dienste. Zunächst einmal, um das Problem der Protokollverfolgung zu lösen, um in der Lage zu sein, dienstübergreifend auf den Aufruf Prozessprotokoll durch eine einheitliche Trace generiert, müssen nun TraceId vereinheitlicht. Die Typen der TraceId dieser Dienste sind jedoch nicht einheitlich, einige verwenden den Typ Long und andere einen String. Außerdem sind die von diesen Diensten verwendeten Sprachen und Technologien nicht einheitlich. Die direkte Verwendung eines Standard-Frameworks für die verteilte Ablaufverfolgung TraceId sollte nicht in der Lage sein, die aktuelle Situation aller Dienste zu unterstützen, sondern kann nur in einigen der Technologie-Stacks der neueren Dienste verwendet werden. Aus Gründen der Kompatibilität und der Einfachheit der Umwandlung werden wir daher den benutzerdefinierten Wert vom Typ Long als TraceId verwenden und die Anzahl der Stellen auf 16 Ziffern begrenzen. Die ersten vier Bits beginnen mit 99, was das Merkmal der vereinheitlichten TraceId ist, und die restlichen zwei Bits identifizieren den Dienst. Die nächsten vier Bits sind die aktuellen Mikrosekunden, und die letzten acht Bits sind zwei Sätze von vier zufällig zusammengesetzten Zahlen. Obwohl diese TraceId keine Eindeutigkeit garantiert, ist sie in der aktuellen Situation ausreichend. Wenn es sich bei dem Dienst um einen Java-Technologie-Stack handelt, muss bei der Generierung der TraceId die Thread-Konkurrenz berücksichtigt werden, am besten weisen Sie jedem Thread einen Zufallszahlengenerator zu. Alternativ können Sie auch direkt TreadLocal verwenden. Der Java-Dienst extrahiert die TraceId aus der Anfrage, wenn die Anfrage verarbeitet wird. Wenn die TraceId mit 99 beginnt, wird keine neue TraceId generiert. Wenn nicht, wird die TraceId wie oben beschrieben erzeugt und im MDC gespeichert. Bei einer asynchronen Ausführung müssen Sie darauf achten, den Inhalt des MDC in den Side-Thread zu kopieren, da sonst die Trace-Informationen verloren gehen. Wenn ein nachgelagerter Dienst aufgerufen werden muss, muss die gespeicherte TraceId an den nachgelagerten Dienst weitergegeben werden. Schließlich muss das MDC geleert werden, wenn die Anfrage verarbeitet wurde, um zu verhindern, dass die Trace-Informationen der nächsten Anfrage verunreinigt werden. ...

Januar 20, 2023

Technischer Bericht für die vierte Woche im Dezember 2022

Diese Woche habe ich mich mit dem COVID-19 angesteckt und war insgesamt 9 Tage zu Hause. In dieser Zeit bestand das Wichtigste bei der Arbeit darin, die Auswirkungen der Förderung und Einführung eines kleinen Programms auf das Basisdienstsystem, für das ich verantwortlich bin, zu bewerten. Diese App traf die Bedürfnisse der Menschen im Land zu dieser Zeit und man erwartete einen großen Zustrom von Besuchern, der sich auf die Kerndienste des Basisdienstesystems auswirken könnte. Ursprünglich hatten sie eine Funktion, die kurz vor dem Start stand, und es gab viel Verkehr, so dass ich die Kapazität bereits bewertet und erweitert hatte. Doch dieses Mal, nachdem sie Hunderte von Millionen von Volumenbenachrichtigungen verschoben hatten, kam es zu einer großen Anzahl von Timeouts. Um 8 Uhr morgens lag ich im Bett und erholte mich, als ich angerufen wurde und mir mitgeteilt wurde, dass es eine massive Zeitüberschreitung auf der Login-Schnittstelle gab. Ich holte sofort meinen Laptop heraus, verband mich mit dem Intranet und stellte fest, dass der Schnittstellenverkehr direkt mehr als 20 Mal stattfand. Ich bin ins Schwitzen gekommen und habe zunächst vermutet, dass die Anzahl der Business-Container nicht ausreicht, um eine so große Menge an Datenverkehr zu bewältigen. Als ich dann die Protokolle durchsah, stellte ich fest, dass dies nicht das Problem ist. Das Problem besteht aus zwei Teilen, zum einen aus einem begrenzten Datenfluss über die interne Schnittstelle, der aktuelle Datenfluss hat das Limit überschritten, zum anderen ist die Cache-Datenbank, die mit der Datenbank verbunden ist, voll. Der interne Schnittstellengrenzfluss ist relativ einfach zu lösen, indem Sie über den Notruf die entsprechenden Kollegen finden, um die Schwelle des Grenzflusses anzuheben. Eine andere Cache-Datenbank, aufgrund der großen Anzahl von alten Benutzern Zustrom führt zu ständig lesen alte Daten aus der Datenbank in den Cache, und die Häufigkeit mit dem Wachstum des Verkehrs weiter zu erhöhen, und schließlich auf den Cache hinter der Datenbank verbunden, um die volle E / A. Im Anschluss an mehrere Kern-Cache-Datenbank, wieder einmal eine Charge von Expansion, verbessern Sie die Cache-Kapazität und die Anzahl der Knoten, um mit den nachfolgenden größeren Verkehr und Gleichzeitigkeit zu bewältigen. Bei der routinemäßigen Wartung geht es vor allem darum, die k8s-Planungsrichtlinie eines Gateway-Service-Pods anzupassen und ihn auf einen Rechenknoten zu planen, der direkt von der CVM-Virtualisierung unterstützt wird (einschichtige Planung). Ursprünglich war der Compute Node, auf dem dieser Dienst geplant wurde, ein CVM, der auf einem physischen Server virtualisiert war, den unser Unternehmen gekauft und als Compute Node verwendet hatte. Nach der Planung auf diesem Knoten wird ein Ausführungsbereich auf diesem CVM virtualisiert (siehe Docker-Technologie), und dann werden Pods auf diesem Knoten geplant, um die Ausführung zu starten (zweistufige Planung). Auf einem Rechenknoten kann es mehrere oder sogar ein Dutzend Pods geben, die auf demselben Betriebssystem, aber mit unterschiedlichen Ausführungsräumen laufen. Dies führt zu einer schlechten Isolierung von CPU, Arbeitsspeicher, Netzwerkkarte und anderen Ressourcen, die sich oft gegenseitig stören. Und wenn dieser CVM-Rechenknoten neu gebootet oder aktualisiert werden muss, werden alle darauf befindlichen Pods evakuiert. Und der Wind im Betriebssystem des Rechenknotens wirkt sich auf alle darauf befindlichen Pods aus. Dies ist für diese Art von Gateway, bei dem es sich um einen Dienst mit hohen Anforderungen an Zuverlässigkeit und Latenzzeit handelt, nicht geeignet. Und eine Schicht von Scheduling Compute Nodes, in der Tat, von der Wolke zu Computing-Ressourcen und virtuelle CVM zuweisen, um dieses Verfahren allein auszuführen, CVM-Ressourcen werden aus dem gesamten Cloud-Ressourcen-Pool erhalten. Und dieser Ansatz unterstützt k8s, denn dieser neue Scheduling-Ansatz wird als eine Art “Superknoten” auf k8s virtualisiert. k8s kann den Pod direkt auf dem Superknoten einplanen, der Pod kann direkt auf einer Schicht des Scheduling basieren, d.h. direkt auf einem separaten CVM laufen. Dieser Ansatz ist hochgradig isoliert und beeinträchtigt sich gegenseitig nicht. Da auf jedem CVM nur ein Knoten läuft, kann ein Problem, das bei einem einzelnen Pod auftritt, für diesen Pod behoben werden, ohne dass andere Pods davon betroffen sind. Wenn Sie die Planungsstrategie ändern und alle Pods des Dienstes auf dem Supernode einplanen, läuft der gesamte Dienst stabiler. Die Situation mit der hohen Timeout-Rate und CPU-Auslastung während der Spitzenzeiten tritt nur noch selten auf. ...

Januar 19, 2023

Technische Überprüfung für die dritte Dezemberwoche 2022

In dieser Woche haben wir vor allem an der Optimierung eines bestimmten Java-Dienstes gearbeitet. Der Dienst hatte Probleme mit der CPU-Auslastung, die nicht hochgefahren werden konnte. Die erste Frage, die sich stellte, war, ob der Dienst ein Problem mit zu wenig Arbeits-Threads hat. Später stellte sich heraus, dass es nicht daran lag, dass die CPU-Auslastung nicht erhöht werden konnte, sondern dass die erhöhte CPU-Auslastung zu mehr Timeout-Problemen führen würde. Der Dienst hatte schon vor langer Zeit die Rückmeldung erhalten, dass die Leistung unzureichend war und es nicht empfohlen wurde, ihn weiter zu nutzen. Ich habe also das Gefühl, dass das Problem vom Framework ausgeht, nicht vom Geschäftscode. Nachdem ich den Code des Frameworks gelesen und durchforstet habe, verwendet das Framework netty als NIO-Server-Framework und verteilt bei der Ausführung der Geschäftslogik die Geschäftsverarbeitungsaufgaben an den Worker-Thread. Der Worker-Thread verarbeitet dann die Geschäftslogik. Ein Problem des vorherigen Frameworks war, dass die Anzahl der Worker-Threads zu gering war, um mit hohen IO-Situationen fertig zu werden. In diesem Fall handelt es sich nicht um das gleiche Problem wie beim letzten Mal, und die Anzahl der Worker-Threads ist den Protokollen zufolge ausreichend. Könnte es ein client-seitiges Problem sein. In der gesamten Microservice-Architektur fungiert der Dienst als Client, der die Schnittstelle anderer Dienste aufruft. Dies könnte ein Einstiegspunkt sein. Beim Durchlesen des Codes habe ich festgestellt, dass das Service-Framework durch die Implementierung der Java-Schnittstelle InvocationHandler eine Proxy-Klasse ObjectProxy erzeugt, die die RPC-Aufrufe an andere Dienste übernimmt. Im Geschäftscode erhält ObjectProxy bei der Initiierung von Aufrufen zu anderen Dienstschnittstellen über RPC eine Liste gültiger Knoten, die dem Zieldienst entsprechen (diese Liste gültiger Knoten wird alle 30s aktualisiert), und zwar mit Hilfe des zugehörigen ProtocolInvoker. Anschließend übergibt er die Liste an den Lastausgleicher LoadBalancer, um den Zielknoten dieses Aufrufs zu ermitteln. Der Aufruf an den Zielknoten erfolgt dann über die protokollspezifische Invoker-Klasse, die für die Verwaltung langer Verbindungen zum Zieldienst zuständig ist und zum Zeitpunkt des Aufrufs eine Verbindung auswählt, an die eine Anfrage gesendet und von der eine Antwort empfangen wird. Die spezifische Anfragemethode hängt davon ab, ob der Aufruf asynchron oder synchron ist. Jeder Zieldienst, den der Client aufrufen muss, besteht aus mehreren Knotenpunkten. Für jeden Knoten erstellt das Framework standardmäßig zwei E/A-Threads für Netzwerk-E/A-Übertragungen (NIO-Modus). Darüber hinaus erstellt das Framework standardmäßig für jeden Knoten eine TCP-Verbindung, die der Anzahl der Prozessoren entspricht. Jeder E/A-Thread enthält einen Selektor, der nach Ereignissen im Zusammenhang mit der Verbindung fragt. Für jede TCP-Verbindung wird eine TCPSession erstellt, und jedes Mal, wenn eine Anfrage gesendet wird, wird ein Ticket erstellt, um die Anfrage und die zugehörige Antwort zu verfolgen. Bei synchronen Anfragen wird die Anfrage gesendet und blockiert, bis die Antwort eintrifft. Bei asynchronen Anfragen wird das Ticket mit einer Callback-Funktion gefüllt. Wenn die Antwort eintrifft, wird die TicketNumber (der eindeutige Index des Tickets) verwendet, um das entsprechende Ticket zu finden und die vorausgefüllte Callback-Funktion zur weiteren Verarbeitung aufzurufen. Das Framework für NIO-Operationen, die zugrundeliegende Verwendung von Java bietet die Möglichkeit der NIO-Bibliothek. Die oben erwähnte TCP-Verbindung, in der Tat ist die NIO-Bibliothek in der SocketChannel. dann das Gerüst, wie das Paket zu teilen, wie es ist, das Gerüst durch den Puffer, um die aktuellen Daten zu speichern wurde gelesen, und wir verwenden in der Regel das RPC-Protokoll, wird das Paket die Anzahl der Bytes in das erste Byte des Pakets, müssen nur die Puffer mit der Anzahl der Bytes der Größe des Pakets können Sie wissen, ob die volle lesen Wenn das Paket nicht gelesen wird, wird es weiter gelesen. Wenn das Paket nicht vollständig gelesen wurde, warten Sie weiter auf die nachfolgenden Daten. Wenn das Paket gelesen wurde, werden die Daten aus dem Puffer entsprechend der Größe der Byteanzahl aufgeteilt und entsprechend verarbeitet. In diesem Framework wird ein zusätzlicher Worker-Thread aus einem Thread-Pool genommen, um die anschließende Verarbeitung des Tickets durchzuführen. Derzeit wird die Arbeit des Thread-Pools nur für diese Aufgabe verwendet, seine Standardanzahl von Threads und die gleiche Anzahl von Kernen, die maximale Anzahl von Threads ist doppelt so hoch wie die Anzahl der Kerne. Gemäß der Definition der Java NIO-Bibliothek gibt es mehrere IO-Operationen, die im Channel spezifiziert sind, und der Selector fragt ab, ob diese Operationen bereit sind, und wenn sie bereit sind, gibt er den SelectionKey zurück. Der SelectionKey enthält die notwendigen Parameter für die richtige Operation, die von dem bereiten Channel ausgeführt werden soll. Nach der Lektüre des Codes gibt es bisher keine offensichtlichen Probleme auf der Client-Seite. Die verwendete Lösung ist im Grunde genommen ausgereift und stabil, so dass es möglich ist, dass das Problem auf der Serverseite liegt, was noch behoben werden muss. ...

Januar 19, 2023

Wöchentlicher technischer Bericht für die zweite Woche im Dezember 2022

In dieser Woche geht es hauptsächlich darum, diesen Aspekt der Arbeit, für die ich verantwortlich bin, zu klären, und bisher wurden viele Probleme identifiziert. Diese Probleme konzentrieren sich hauptsächlich auf die Daten in der Cloud. Das aktuelle Problem ist vor allem die Frage, wie man die Daten sicher in der Cloud speichern kann, wie man das derzeitige Schema für die Bereitstellung in einer einzigen Geographie umwandeln kann und wie man die Inkonsistenz zwischen den Daten unter der Cloud und den Daten in der Cloud beheben kann. Außerdem wird festgestellt, dass es immer noch einige Dienste gibt, die Under-Cloud-Datenbanken verwenden, und dass diese Under-Cloud-Datenbanken vernünftigerweise aufgegeben werden sollten. Bei diesen Diensten handelt es sich jedoch um einige alte Dienste, und Code-Änderungen bringen einige Risiken mit sich, die untersucht werden müssen, bevor Maßnahmen ergriffen werden. Zu den Aspekten der Untersuchung gehören die grundlegenden Prinzipien der bestehenden Daten zu den Cloud-Hilfsdiensten und die damit verbundenen Details der Codelogik. Es ist am besten, die Probleme so früh wie möglich herauszufinden und sie rechtzeitig zu beheben. Andererseits muss der Prozess der Datenübertragung in die Cloud in Echtzeit überwacht werden, und zwar so umfassend wie möglich in Bezug auf die Qualität der Schnittstellenaufrufe des Dienstes, die Timeout-Rate, die Fehlerrate beim Schreiben, die Inkonsistenzrate usw., um einen klaren Überblick zu erhalten. Dieser Aspekt wird am besten durch die Überwachung von Berichten und Protokollen gewährleistet. Was das Bereitstellungsschema für mehrere Standorte anbelangt, so besteht die derzeitige Absicht darin, eine einseitige Master-Slave-Replikation zu verwenden, nur die Master-Bibliothek zu beschreiben und nur von der Bibliothek zu lesen. Der Hauptzweck der Verwendung eines Multi-Location Deployment Schemas ist es, die Stabilität des Dienstes zu verbessern, die Latenz der meisten Anfragen zu reduzieren, die Qualität des Dienstes zu verbessern und die Auswirkungen der Instabilität der regionsübergreifenden Verbindungen zu beseitigen. Die Verzögerungen bei der Datensynchronisierung an mehreren Standorten können nicht ignoriert werden. Es muss eine akzeptable Verzögerung geben, die in der Theorie und bei der Überwachung unter zwei Aspekten zu verstehen ist. Andererseits ist es wichtig, eine Skriptsprache zu beherrschen. Vor allem dann, wenn viele sich wiederholende Dinge verarbeitet werden müssen oder wenn Daten analysiert werden müssen, um eine Schlussfolgerung zu ziehen. Eine Skriptsprache wie Python besser zu beherrschen, ist ein großer Vorteil. Allerdings halte ich es nicht für klug, zu sagen, dass es eine gute Idee wäre, mit Python ein großes Programm zu schreiben. Jede Programmiersprache ist wie ein anderes Messer. Alle können zum Schneiden von Gemüse verwendet werden, aber manche Messer sind besser geeignet, um Fleisch oder Knochen zu schneiden. ...

Dezember 13, 2022

Wöchentlicher technischer Bericht für die erste Woche im Dezember 2022

Zusammengefasst ging es in dieser Woche vor allem darum, einen Kerndienst in die Cloud zu bringen und dann die Knoten unter der Cloud kontinuierlich in Verkehrsweiterleitungsknoten umzuwandeln. Der erste Schritt in der Cloud ist die Bereitstellung des Serviceknotens in der Cloud-Umgebung: Migrieren Sie die Konfigurationsdateien, die Umgebung und kompilieren Sie dann das Image für die Cloud-Umgebung entsprechend der stabilen Version des Codes, und lassen Sie den Service in der Cloud-Umgebung hochlaufen. Nachdem der Dienst hochgefahren und der Test abgeschlossen ist, ist auf dem Knoten in der Cloud derzeit kein Datenverkehr zu verzeichnen. Jetzt müssen Sie einen Teil des Datenverkehrs unter der Cloud in die Cloud weiterleiten, indem Sie zunächst einige der Knoten unter der Cloud durch Weiterleitungsknoten ersetzen. Später kann dieser Teil des Datenverkehrs dazu verwendet werden, den Arbeitsstatus der Knoten in der Cloud zu beobachten und auf Anomalien zu prüfen, was als “Verkehrsgrauskala” bezeichnet werden kann. Die Graustufe des Datenverkehrs wird in der Regel in der Rolle des Gesamtdatenverkehrs 1 %-5% kontrolliert, je nach Kritikalität des Dienstes, um das Verhältnis anzupassen, kann die Testumgebung angemessener sein, 25 %-50% sein kann. Verkehr grau ist, wenn ein Problem auftritt, oder wenn Sie ein Problemticket erhalten, müssen Sie nur den Verkehrsweiterleitungsknoten unter der Cloud herunterfahren. Natürlich muss alles oben Genannte zunächst in der Testumgebung betrieben werden. Testen Sie diese ordnungsgemäß und folgen Sie dann demselben Schema, um die Produktionsumgebung sorgfältig zu betreiben. Einige der Backend-Systeme sind kompliziert, ein Aufruf mit mehreren Diensten, die Geschäftslogik ist verwirrend, versuchen Sie diesmal, die Variablen für eine gewisse Zeit zu kontrollieren, um nur eine Änderung vorzunehmen, und beobachten Sie eine gewisse Zeit, bis sich die Situation stabilisiert hat, und führen Sie dann die nächste Operation durch. Oder Sie können den großen Schritt in mehrere kleine Schritte aufteilen, eine Zeitspanne lang nur einen kleinen Schritt machen, nach einer Zeitspanne beobachten und dann den nächsten kleinen Schritt vorantreiben. Dies ist weniger anfällig für Fehler. Als nächstes, wenn die Graustufenprüfung bestanden ist (dauert in der Regel eine Woche). Der nächste Schritt besteht darin, die Routen zu wechseln. Das Umschalten der Routen bedeutet, dass die Routen vom Dienstknoten in der Cloud direkt auf den On-Cloud-Knoten umgeschaltet werden, woraufhin der andere On-Cloud-Masterdienst direkt auf den On-Cloud-Knoten für diesen Dienst zugreift und den Off-Cloud-Knoten nicht mehr besucht. Bei der Umstellung des Routings ist besondere Vorsicht geboten, da ein großer Teil des Online-Verkehrs direkt auf den On-Cloud-Knoten zugreifen wird. Vor dem Betrieb müssen Sie zunächst die Anzahl der benötigten Knoten in den einzelnen geografischen Regionen der Cloud auf der Grundlage der üblichen Daten berechnen, in der Regel in Übereinstimmung mit dem Spitzenverkehrsaufkommen, wenn dies nicht ausreicht, um die Kapazität zu erweitern, damit es auf der Leitung nicht zu einer großen Anzahl von Timeouts aufgrund unzureichender Kapazität kommt. Zu diesem Zeitpunkt wäre es besser, wenn die Anzahl der Knoten in der Cloud höher wäre, da sie später langsam reduziert werden kann und die Kosten nicht hoch sind. Wenn es jedoch weniger Knoten gibt, die eine große Anzahl von Timeouts verursachen, braucht die Erweiterung der Knoten Zeit (vor allem die zeitaufwändige Planung der Ressourcen und der Start des Dienstes), was zu Beschwerden der Benutzer führen kann. Wenn die Zeitüberschreitung viele Client-Wiederholungsversuche auslöst, kann sie den gesamten Dienst zum Absturz bringen und Online-Unfälle verursachen. Damals habe ich eine Zeit gewählt, in der der Datenverkehr gering war, um die Auswirkungen des Umschaltjitters zu verringern. Nach der Umschaltung der Route können die Knoten unter der Cloud nach und nach zu Weiterleitungsknoten werden und den gesamten Datenverkehr unter der Cloud zur Verarbeitung an die Cloud weiterleiten. Dann benachrichtigen Sie die für den primären Dienst zuständige Person, damit diese versucht, den Dienst in die Cloud zu bringen. Denn die Weiterleitung von Knoten an die Cloud ist mit Overhead verbunden und erhöht die Latenzzeit. ...

Dezember 9, 2022