Wöchentlicher technischer Bericht für die vierte Woche im November 2022

Diese Woche habe ich mich hauptsächlich mit der Optimierung eines Dienstes beschäftigt. Dieser Dienst ist in Java geschrieben. Wenn in der Produktionsumgebung nicht viel Verkehr herrscht, gibt es auch eine Zeitüberschreitung für den Aufruf von Batches. Und wenn die Zeitüberschreitung gesendet wird, ist die CPU-Auslastung niedrig. Bei der Beobachtung stieg die CPU-Auslastung nie an. Zu diesem Zeitpunkt wurde spekuliert, dass alle Threads bei einer bestimmten Operation blockiert waren und das Problem verursachten. Die meisten der Dienste, mit denen ich gearbeitet habe, einschließlich dieses Dienstes, sind IO-intensiv. Diese Art von Diensten beinhaltet viele RPC-Aufrufe, und wenn RPC-Aufrufe erfolgen, blockieren die Worker-Threads und machen es unmöglich, andere Anfragen zu bearbeiten. Daher wird die Anzahl der Worker-Threads für diese Art von Diensten sehr hoch angesetzt, um sicherzustellen, dass zusätzliche Threads für die Bearbeitung von IO-Anfragen zur Verfügung stehen, so dass nachfolgende Anfragen nicht bearbeitet werden können, weil die Mehrheit der Threads blockiert, was letztendlich zu einer großen Anzahl von Timeouts führt. Das ist tatsächlich problematisch, obwohl Java das NIO-Modell beim Umgang mit Sockets und beim Parsen von Anfragen übernommen hat, aber die logische Verarbeitung der Anfrage verwendet immer noch einen Pool von Worker-Threads. Wenn ein Worker-Thread bei der IO-Anfrage blockiert ist, kann der Worker-Thread nur warten, bis die IO-Anfrage abgeschlossen ist oder eine Zeitüberschreitung eintritt. Wenn das von der IO-Anfrage zurückgegebene Ergebnis nicht vom Endergebnis der Anfrage abhängt, wird die Anfrage an einen anderen Thread-Pool zur Verarbeitung weitergeleitet. Diesmal ist die Verarbeitung für diesen Worker-Thread asynchron. Nach der Fehlersuche stellte sich schließlich heraus, dass dieser Dienst eine Konfiguration über die Anzahl der Worker-Threads hatte, die aufgrund eines Framework-Problems nicht gelesen wurde. Dies führte dazu, dass der Dienst mit der Standardeinstellung für die Anzahl der Worker-Threads startete, die der Anzahl der CPU-Kerne entspricht. Wenn die Worker-Threads also nachgelagerte RPC-Aufrufe verarbeiteten, führte jede kleine Schwankung in der verstrichenen Zeit der nachgelagerten Schnittstelle dazu, dass eine große Anzahl von Anfragen einen Timeout verursachte. Zu diesem Zeitpunkt ist auch die CPU-Auslastung gering, da die Worker-Threads die meiste Zeit blockiert sind und auf die Rückkehr der IO-Operation warten. Wie Sie das Problem beheben können, müssen Sie zunächst im Protokollrahmen den Namen des aktuellen Threads für den Logback-Protokollrahmen ausgeben lassen, d.h. in den Einstellungen für das Protokollformat % t hinzufügen. Dann einen einzelnen Knoten in der Testumgebung für Drucktests, um in einer bestimmten QPS den Dienst für die Anfrageverarbeitung zu sehen. Am besten fügen Sie StopWatch zum logischen Code der Anfrage hinzu, um die Analyse zu unterstützen. Schließlich stellen Sie fest, dass das Ausgabeprotokoll nur von einigen wenigen Threads stammt, was nicht stimmt. Verwenden Sie dann jstack, um die Anzahl der Threads herauszufiltern. Sie stellen fest, dass es tatsächlich nur vier sind. Dies lässt sich damit erklären, dass das von diesem Java-Dienst verwendete Framework das netty-Framework für die Verarbeitung von Anfragen verwendet und diese schließlich an den netty-Worker-Thread-Pool weitergeleitet werden, um die Anfragelogik zu verarbeiten. In diesem Fall entspricht der netty worker thread pool dem Präfix nioEventLoopGroup-5. Darüber hinaus kann anhand der kumulativen CPU-Zeit nachgewiesen werden, dass es wirklich nur diese vier Threads gibt, die die gesamte Hauptlogik der Anfrage verarbeiten. Für diese Art von Dienst wird in der Produktionsumgebung die Anzahl der Worker-Threads in der Regel auf 800~1000 festgelegt und die Zeitüberschreitung für RPC-Aufrufe wird streng eingestellt, um zu verhindern, dass eine große Anzahl von Worker-Threads blockiert wird, was letztendlich zu einem drastischen Rückgang des Durchsatzes des Knotens führt. Nachdem ich das Framework aktualisiert hatte, war das Problem gelöst. Außerdem entdeckte ich, dass eine der wichtigsten Schnittstellen des Dienstes einen nachgelagerten Aufruf auf der Grundlage des http-Protokolls enthielt. Der Aufruf erfolgte durch Manipulation der OkHttp-Bibliothek, und ich stellte fest, dass der Aufruf kein Timeout setzte. Das ist falsch, denn in einer extremen Situation, in der der Downstream verzögert zurückkehrt, wird der Worker-Thread lange Zeit blockiert. Daher müssen Sie eine angemessene Timeout-Zeit für Downstream-Aufrufe festlegen, um den reibungslosen Ablauf zwischen Upstream- und Downstream-Aufrufen zu gewährleisten und das Auftreten von Lawinen zu verhindern. Die Timeout-Zeit wird im Allgemeinen in drei Arten unterteilt: Verbindungs-Timeout, Lese-Timeout und Schreib-Timeout, die alle festgelegt werden müssen. Außerdem habe ich für die mögliche Existenz einer großen Anzahl von Http-Aufrufen den OkHttp ConnectionPool aktiviert. Laut der Dokumentation besteht der Vorteil von ConnectionPool darin, dass sich mehrere http- oder http/2-Anfragen an dieselbe Adresse dieselbe Verbindung teilen können. Es sei jedoch darauf hingewiesen, dass die Voraussetzung für diese gemeinsame Nutzung ist, dass die Serverseite eine lange http-Verbindung unterstützt. Außerdem haben wir uns in dieser Woche hauptsächlich mit den TCP-Inhalten des Tencent Cloud’s Advanced Architect beschäftigt, da die Prüfung am Wochenende angesetzt ist. Diese TCP-Prüfung ist etwas schwieriger als die ursprünglichen Architect- und Practitioner-Prüfungen, so dass Sie sich trotzdem darauf vorbereiten müssen. Ich hatte auf der Arbeit nicht viel Zeit, um mir den Stoff anzusehen, also habe ich den schweren Stoff direkt bis 5 Uhr morgens am Samstag durchgearbeitet und zum Glück habe ich die Prüfung am Ende bestanden. Ich sollte einen Artikel über diese Prüfung schreiben. ...

November 27, 2022

Technische Überprüfung für die dritte Woche im November 2022

Dies ist der erste meiner regelmäßigen Rückblicke auf technische Probleme, die mir bei der Arbeit begegnet sind. Dieser Rückblick ist also hauptsächlich eine Zusammenfassung der Erfahrungen, die ich im Laufe der Zeit gemacht habe, um einen Vorsprung für künftige technische Rückblicke zu erhalten. Ich arbeite jetzt seit fast sechs Monaten in dem Unternehmen und habe vor kurzem von der clientseitigen Entwicklung zur Backend-Entwicklung gewechselt. Das ist das, was ich mir wünsche, aber eigentlich nicht das, worum ich gebeten habe. Denn ich persönlich habe das Gefühl, dass Backend-Entwickler in der aktuellen Karriereplanung der chinesischen Tech-Industrie etwas mehr Möglichkeiten haben und viel mehr mit Problemen konfrontiert werden. Auch die Client-Seite ist vielversprechend. Mein erstes ausgereifteres Open-Source-Projekt, GpgFrontend, ist ein clientseitiges Projekt. Ich habe viel Zeit darin investiert und eine Reihe von Problemen gelöst. Vor allem Kompilierungsprobleme, Probleme mit der Plattformkompatibilität und Stabilitätsprobleme. Die Tiefe seiner Erforschung, die Schwierigkeit des Problems, sind nicht gering. Ich habe das Gefühl, dass der Grund für die Aufteilung der Client- und Backend-Entwicklung in eine hohe und eine niedrige Stufe darin liegt, dass das Herz nicht zur Ruhe kommt und immer daran denkt, aufzusteigen. Darüber hinaus für die Ausübung der Technologie ursprünglich keine Rolle Client-, Front-End-oder Back-End, die technischen Ideen hinter ihnen sind im Wesentlichen gemeinsam, aber die aktuelle Besetzung ist zu wichtig, aber statt der beruflichen Arbeitsteilung, um die Technologie klar zu teilen. Ich denke, das ist nicht gut, so dass, obwohl ich derzeit ein Back-End-Entwickler, aber ich darf nicht denken, dass ich nur ein Back-End-Entwickler, andere Technologien nicht sehen, nicht lernen, ihr eigenes Denken Box auf. Nun, da sich die Position zum Backend-Entwickler geändert hat, weiß ich nicht, was ich stattdessen tun soll. Backend-Entwicklung, ich erinnere mich gerade daran, dass das früheste Backend-Projekt, das ich selbst geschrieben habe, ein Astronomieforum Stelescope war, das in Nodejs geschrieben wurde, als ich 15 Jahre alt war. Es verwendete das Express-Framework, das damals sehr beliebt war. Ich erinnere mich noch gut daran, wie ich zum ersten Mal mit technischen Konzepten wie MongoDB, dem Speichern von Zuständen für die An- und Abmeldung, asynchronen Callbacks usw. bekannt gemacht wurde. Am meisten erinnere ich mich an die asynchronen Rückrufe, bei denen ich lange brauchte, um sie zu verstehen. Es dauerte lange, bis ich es verstand, weil ich nicht einmal die grundlegenden Konzepte von Prozessen und Threads kannte, geschweige denn asynchrone Rückrufe und Closures. Damals wurde im Internet noch über die Vor- und Nachteile von Nodejs und PHP gestritten, Nodejs eignet sich für welche Szenarien, und dann sind asynchrone Rückrufe und Multiprozessparallelität besser oder schlechter. Damals erinnerte ich mich daran, dass asynchrone Rückrufe nicht blockiert werden können. Wenn Sie auf eine blockierende Operation stoßen, verwenden Sie eine nicht blockierende API, die sofort zur blockierenden Operation zurückkehren kann, um sie zu bearbeiten, während der Hauptthread weiterhin mit dem nachfolgenden Code arbeiten kann. Wenn die blockierende Operation beendet ist, wird der Hauptthread benachrichtigt, die Callback-Funktion auszuführen, um die Ergebnisse der blockierenden Operation zu verarbeiten. Anschließend lernte ich auch die Python-Backend-Entwicklung kennen und schrieb ein einfaches System zur Verwaltung der Anwesenheit von Schülern (SP ). Hier wurde ich mit der Idee von MVC vertraut gemacht, was ich als Model, View und Controller verstehe. Das ist eine wichtige Idee, denn zu dieser Zeit war das Konzept des Frontends noch nicht sehr klar, die Trennung von Frontend und Backend war noch nicht die gängige Idee. Damals war der Server für die dynamische Seitengenerierung zuständig, und der Controller wurde durch die Anfrage veranlasst, zu antworten. Controller führten Berechnungen auf der Grundlage des Modells durch und renderten das Modell schließlich über eine Template Engine in eine Seite, die dann an den Browser des Benutzers zurückgegeben wurde. Es ist einfach ein Prozess. Ich erinnere mich, dass wir damals eine Menge Vorlagen auf der Serverseite definiert haben, Vorlagen, um einige Stellen auszuhöhlen, um später Daten zu speichern. Oder Sie definieren eine kleine Kartensteuerung, fügen die for-Anweisung ein und verwenden dann die Template-Engine, um eine Vielzahl von Karten zu erzeugen. Zu diesem Zeitpunkt muss ich als Backend-Entwickler jeden Aspekt berücksichtigen, einschließlich der Schönheit der Seite, der Datensicherheit, der schnellen Reaktion und so weiter. Im nächsten Jahr kam ich dann mit dem Spring-Framework in Berührung, insbesondere mit SpringBoot. Diesmal verstand ich nur die relationale Datenbank. Es stellte sich heraus, dass mein Verständnis von relationalen Datenbanken nur darin bestand, sie zu installieren und zu konfigurieren. Ich erinnere mich noch gut daran, als ich mit der Idee der Trennung von Front-End und Back-End in Berührung kam, die ich für eine gute Sache halte. Ich nahm die Idee auf und diskutierte sie mit Herrn Wang, indem ich sagte, dass es am besten wäre, die Trennung von Front-End und Back-End für unser System zur Verwaltung der gesamten Bildung zu verwenden. Herr Wang war sehr aufgeschlossen, hat viel mit mir gesprochen und meinem Vorschlag zugestimmt. Die Trennung von Front-End und Back-End bedeutet, wie der Name schon sagt, dass das dynamische Rendering der Seiten auf die Benutzerseite verlagert wird und der Server nur für die Datenverarbeitung und -speicherung zuständig ist. Das fördert die Arbeitsteilung und Entkopplung, obwohl es damals auch viele Zweifel im Internet gab, glaube ich immer noch, dass dies der Trend ist. Damals war ich besessen von einer Art RestfulAPI-Schnittstellenspezifikation und ich dachte, dass wir damit sogar das Schreiben von Projektdokumenten vermeiden könnten. Aber die Realität sieht ganz anders aus. In der Praxis ist es für einige komplexe Fälle schwierig, den Stil von RestfulAPI beizubehalten. Durch die Beschäftigung mit SpringBoot habe ich eine Menge über das Backend gelernt, und diese ursprünglichen Erfahrungen nutze ich jetzt. Während meines Studiums habe ich eine Menge SpringBoot-Projekte geschrieben. Inzwischen war ich in das Unternehmen eingetreten und hatte herausgefunden, dass der Tech-Stack der Abteilung Java war und das Framework, das für neue Projekte verwendet wurde, SpringBoot war, in umgekehrter Richtung. Obwohl ich gesagt habe, dass ich von Java angewidert bin, weil ich es für aufgebläht und schwerfällig halte, habe ich auch jetzt kein gutes Gefühl, aber das Java-Ökosystem ist in der Tat sehr leistungsfähig, es ist sehr einfach, eine Komponente zu finden, und die Java-Komponenten sind ausgereift, gut gewartet und gut dokumentiert. Java-Technologie-Stack für produktionsorientierte Back-End-Projekte, es ist wirklich eine problemlose, gute, einen Job für den Technologie-Stack zu finden. Ich arbeite seit einem halben Jahr in dem Unternehmen, wenn man die Praktika mitzählt, ist es sogar schon fast ein Jahr. Im Allgemeinen habe ich mich für den Hintergrund dieses Artikels mit Optimierung, Caching, Threading und diesen Dingen beschäftigt. Ich habe jeden Tag alle Arten von Meldungen analysiert, von denen einige geschäftlicher und einige technischer Natur sind. Bei geschäftlichen Problemen können Sie nur den Hintergrund gut verstehen. Bei technischen Problemen müssen Sie Ihr Wissen erweitern und in Ruhe studieren. So gibt es z.B. bei der Bereitstellung von Containern immer wieder Timeout-Probleme. Ich konnte nicht feststellen, ob es sich dabei um ein Container-Problem oder ein Problem mit einer Hintergrundanwendung handelt. Ich denke jetzt, dass dieses Stück etwas tiefer gehendes Wissen erfordert, wie die Virtualisierung von CPU, Speicher und Netzwerk. Das war’s für heute, es gibt noch ein paar andere Dinge zu tun. ...

November 20, 2022

Ziehen Sie Ihre eigenen praktischen Lektionen zur Entwicklung von Gewohnheiten

Viele Menschen möchten eine gute Gewohnheit entwickeln, denn eine gute Gewohnheit kann noch lange Zeit etwas Gutes bewirken. Diese gute Sache wird jedes Mal, wenn Sie sie tun, eine gewisse Menge an gutem Einfluss mit sich bringen. Und eine gute Auswirkung, die sich immer wieder einstellt, kann nach einer relativ langen Zeitspanne bei einem Menschen einige Aspekte einer großen positiven Veränderung bewirken. Viele Menschen versuchen, Gewohnheiten zu entwickeln, haben aber Schwierigkeiten, sie beizubehalten. Stattdessen greifen sie auf viele äußere Kräfte zurück, um sich selbst zu “überwachen”, was sie wiederum noch schmerzhafter macht. Ich glaube, die Ursache dafür ist das Fehlen einer starken intrinsischen Motivation. Nehmen wir an, Sie möchten eine Fremdsprache lernen. Sie wissen, dass das Erlernen einer Fremdsprache alle möglichen Vorteile mit sich bringen kann. Aber Sie wissen im Grunde Ihres Herzens, dass diese Vorteile nur das Sahnehäubchen auf dem Kuchen sind und Ihre Zukunft nicht beeinflussen werden. Machen Sie sich nichts vor, und ich will damit nicht sagen, dass es wichtig ist, sich immer wieder einzureden, dass das Erlernen einer Fremdsprache wichtig ist. Was ich damit sagen will, ist, dass Sie das Erlernen einer Fremdsprache für sich wirklich wichtig machen müssen, damit es effektiv ist. Nehmen wir zum Beispiel an, Sie haben sich im Rahmen Ihrer Lebensplanung für ein Studienprogramm im Ausland angemeldet und viel Geld für einen Vertrag ausgegeben. Sie sind jetzt in einer Situation, in der Sie es sich nicht leisten können, es nicht zu lernen. Wenn Sie es nicht lernen, wird Ihr Lebensplan nicht erfüllt und das Geld, das Sie für die Unterzeichnung des Vertrags ausgegeben haben, ist futsch. Auf diese Weise wird ein starker innerer Antrieb geschaffen. Wenn dieser innere Antrieb erst einmal da ist, wird er Sie ständig daran erinnern und Sie dazu anspornen, automatisch ein Fremdsprachenbuch in die Hand zu nehmen. Solange Sie keinen Grund haben, es abzulehnen, wird Ihre Faulheit nicht an Ihnen vorübergehen. Ein weiterer wichtiger Punkt, den ich herausgefunden habe, ist, dass Gewohnheiten im Einklang mit der Natur und vor allem im Einklang mit Ihrem eigenen Herzen entstehen. Sie können sich z.B. keine Gewohnheit machen, die Sie nicht mögen. Wenn Sie etwas nicht mögen und Sie sich dazu zwingen müssen, dann werden Sie es letztendlich nicht tun können. Ob Sie etwas mögen oder nicht, hängt in erster Linie davon ab, ob Sie ein Gefühl der Freude haben, bevor Sie es tun, können Sie daran denken, was Sie gewinnen können, nachdem Sie es getan haben, was Ihnen ein Gefühl der Freude gibt. Es gibt ein Gefühl der Freude, das Sie von Zeit zu Zeit daran erinnern kann, etwas zu tun. Der dritte Punkt ist, dass Sie nicht ständig, sondern über einen längeren Zeitraum dabei bleiben sollten. Man kann nicht sagen, dass Sie sich zwingen müssen, eine bestimmte Gewohnheit ständig beizubehalten, denn Gewohnheiten ändern sich langsam, wenn Ihr Leben weitergeht. Bleiben Sie über einen längeren Zeitraum dabei, was bedeutet, dass Sie es über einen langen Zeitraum hinweg regelmäßig tun werden. Nur weil Sie es ein- oder zweimal nicht tun, heißt das nicht, dass die Gewohnheit verschwunden oder gebrochen ist. Da die Dinge nicht reibungslos ablaufen, gibt es immer wieder Wiederholungen. Gönnen Sie sich also ein wenig Zeit, um die Dinge anders zu machen oder die Sache nicht zu tun und sich in einen entspannteren Zustand zu versetzen. Denken Sie daran, dass der Überschuss das Defizit ist, also lassen Sie sich immer ein wenig schwimmen, erlauben Sie sich ein kleines Faulenzen, der Prozess der Gewohnheitsbildung wird keine großen Racheschwankungen haben. Im Laufe der Entwicklung von Gewohnheiten werden Sie vielleicht feststellen, dass diese Gewohnheit nicht gut ist oder nicht zu Ihnen passt. Zu diesem Zeitpunkt sollten Sie die Gewohnheit entschlossen aufgeben. Denn die Bildung von Gewohnheiten ist eine positive Rückkopplung, ein Prozess, bei dem Sie sich selbst motivieren und Gewinne erzielen, und nicht ein Prozess, bei dem Sie sich selbst und Ihr inneres Selbst in die Zange nehmen. Eine weitere Sache ist, dass die Gewohnheitsbildung Ihre normale Routine nicht beeinträchtigen sollte. Sie können nicht sagen: “Heute lerne ich den Text auswendig”, es dann aufgrund unvorhergesehener Umstände nicht tun und es dann spät in der Nacht zu Ende bringen, wodurch Sie aus dem Bett gezwungen werden. Das ist die Mühe nicht wert, sondern führt aufgrund der Unterbrechung ihres Lebenszyklus in eine Situation der Erschöpfung, die dazu führt, dass Gewohnheiten immer schwerer zu entwickeln sind. Und schließlich: Woher wissen Sie, ob sich eine Gewohnheit entwickelt hat? Wenn Sie feststellen, dass etwas zu fehlen scheint, wenn Sie es heute nicht tun. Oder wenn Sie sich automatisch daran erinnern, es zu einer bestimmten Zeit zu tun. An diesem Punkt können Sie die Gewohnheit als gebildet betrachten, Sie machen einfach mit, genießen die Gewohnheit der Trägheit, um Ihnen Glück zu bringen, dabei können Sie weiterhin ihr eigenes Wachstum und Glück in einem bestimmten Bereich ernten. ...

April 22, 2022