In großen monolithischen Anwendungen sind Fehlerverfolgung und -überwachung aufgrund fehlender klarer Verantwortlichkeiten oft ineffektiv. Dieser Leitfaden behebt das Problem, indem er einen strukturierten Ansatz zur Zuweisung von Verantwortlichkeiten durch Domänenanmerkungen vorschlägt.
Das Einrichten einer effektiven Überwachung für große monolithische Systeme mit mehreren Teams kann eine Herausforderung sein. Ohne klare Zuständigkeit wird die Fehlerverfolgung generisch und oft ignoriert. Eine Lösung besteht darin, dass Bereitschaftstechniker bestimmen, welches Team auf Überwachungsalarme reagieren soll. Ein effizienterer Ansatz besteht jedoch darin, Domänen- und Teaminformationen in jedes Protokoll und jeden Datadog-Span aufzunehmen.
Um den Überblick darüber zu behalten, welches Team für welche Teile unserer Anwendung verantwortlich ist, verwenden wir ein System namens Domain Annotations. Domain Annotations kennzeichnen jeden Teil des Codes Ihrer Anwendung und geben deutlich an, wer für was verantwortlich ist. Dies sorgt für klare Organisation und Verantwortlichkeit bei der Verwaltung von Verantwortlichkeiten.
Domänenanmerkungen bieten eine klare und organisierte Methode, um Teamverantwortlichkeiten innerhalb einer monolithischen Anwendung zu verfolgen. Indem Sie Teile Ihres Codes mit Domänenanmerkungen kennzeichnen, können Sie:
Um eine effiziente Überwachung und Nachverfolgbarkeit zu gewährleisten, wird jede Webanforderung mit den entsprechenden Domäneninformationen versehen. Dies wird durch die Zusammenarbeit mehrerer Komponenten erreicht: DomainProvider
, DomainSpanService
, DomainMdcProvider
und DomainHandlerInterceptor
.
Hier ist eine allgemeine Übersicht über den im folgenden Diagramm dargestellten Prozess:
Die detaillierte Implementierung dieser Komponenten wird in einer gemeinsam genutzten Bibliothek gekapselt und bietet eine wiederverwendbare Lösung zum Markieren und Überwachen von Webanforderungen in großen monolithischen Anwendungen.
Die Definition des Eigentums auf Klassenebene ist mit Domänenanmerkungen unkompliziert. Durch die Anwendung von Anmerkungen der obersten Ebene auf Hauptklassen wird das Eigentum auf alle detaillierten Ressourcen innerhalb dieser Klassen übertragen. Jedes Team kann Klassen, die ihm gehören, mit den entsprechenden Domänenanmerkungen kennzeichnen und so für Klarheit und Verantwortlichkeit sorgen, ohne dass jede einzelne Methode markiert werden muss.
In Fällen, in denen mehrere Teams Code in einer Klasse besitzen und eine sofortige Umgestaltung nicht angebracht ist, können Sie einzelne Methoden mit unterschiedlichen Domänenanmerkungen markieren, die Vorrang vor Anmerkungen auf Klassenebene haben. Dadurch können bestimmte Methoden verschiedenen Teams zugewiesen werden, was Flexibilität bietet, ohne die Gesamtstruktur zu verkomplizieren.
Obwohl Domänenanmerkungen unglaublich nützlich sind, gibt es seltene Fälle, in denen sie nicht verwendet werden können. Beispielsweise traten bei der Joberstellung von Quartz Probleme auf, die aufgrund eines Konflikts zwischen der AOP-Logik von Quartz und der für Domänenanmerkungen verwendeten AOP-Logik nicht reibungslos mit Domänenanmerkungen funktionierten.
Für Jobs und Prozesse, die nicht direkt annotiert werden können, haben wir den DomainTagsService direkt in den Jobimplementierungen verwendet. Mit diesem Ansatz konnten wir Domänen-Tags manuell in die Ausführungslogik des Jobs einfügen.
Hier ist ein Beispiel, wie wir DomainTagsService in einen Quartz-Job integriert haben:
final override fun execute(context: JobExecutionContext) { domainTagsService.invoke(domain) { withLoggedExecutionDetails(context, ::doExecute) } }
Während separate Dienste für jedes Team erhebliche Vorteile bei der Überwachung und dem Besitz bieten, ist die Aufteilung des Monolithen mit hohen Kosten und Aufwand verbunden und kann zusätzliche Entwicklungskosten verursachen. Angesichts der Möglichkeit, die Build-Zeiten mit Gradle zu verbessern, wenn der Monolith in Module aufgeteilt wird, ist die Pflege eines Monorepo in vielen Fällen möglicherweise die effizienteste Lösung.
Um die Überwachung der Aktivitäten jedes Teams in Datadog zu vereinfachen, können Sie künstliche Dienstnamen für Bereiche verschiedener Teams zuweisen. Dieser Ansatz stellt sicher, dass jedes Team seinen eigenen Bereich in den Überwachungstools von Datadog hat. Die Verwendung künstlicher Dienstnamen kann zwar verwirrend sein, wenn Sie viele Dienste verwalten müssen, aber bei einer begrenzten Anzahl von Backend-Diensten ist sie überschaubar. Das Hinzufügen von Präfixen zu diesen künstlichen Dienstnamen trägt dazu bei, die Organisation und Übersichtlichkeit Ihres Datadog-Setups aufrechtzuerhalten und erleichtert die Unterscheidung zwischen verschiedenen Teams und ihren Verantwortlichkeiten.
Diagramm statt Screenshot verwenden?? Worker/Webapp zu haben macht hier keinen Sinn
Die Verwendung künstlicher Dienstnamen für Protokolle kann zu Verwirrung führen, da derselbe Protokolleintrag unter verschiedenen Diensten erscheinen kann.
Betrachten wir beispielsweise zwei Endpunkte, die denselben Authentifizierungsdienst verwenden. Wenn diese Endpunkte mit unterschiedlichen Domänen annotiert sind, erzeugt die Authentifizierungslogik Protokolle unter unterschiedlichen künstlichen Diensten. Dies kann bei der Untersuchung von Protokollen zu Verwirrung führen, da sie unter mehreren Dienstnamen erscheinen. Um dieses Problem zu vermeiden, ist es besser, künstliche Dienstnamen nur auf Bereiche anzuwenden, die in Spuren zusammengefasst sind, damit es weniger Verwirrung gibt.
Macht das irgendeinen Sinn? Ich glaube nicht
Hier ist eine visuelle Darstellung dieses Problems:
Durch die Verwendung künstlicher Dienste können Sie nicht nur mit APM-Traces arbeiten, sondern auch nach Diensten in Datadog-Metriken filtern, die über einen längeren Zeitraum gespeichert werden, sodass Änderungen über einen längeren Zeitraum verfolgt werden können.
Unten sehen Sie einen Screenshot eines Monitors in Datadog, der in der Abfrage den künstlichen Dienstnamen konsus-assets
verwendet:
Unten sehen Sie einen Screenshot eines Dashboards in Datadog, das im Filter den künstlichen Servicenamen konsus-assets
verwendet:
Durch die Verwendung von Fake-Services in Ihrer Überwachungsstrategie können Sie die Sichtbarkeit und Verantwortlichkeit der Aktivitäten jedes Teams innerhalb einer monolithischen Anwendung verbessern. Dieser Ansatz vereinfacht die Erstellung und Pflege teamspezifischer Monitore und Dashboards und führt zu einer effektiveren und organisierteren Überwachung in Datadog.
Domänenanmerkungen bieten einen unkomplizierten Ansatz zur Vereinfachung der Überwachung monolithischer Anwendungen in Datadog. Durch die Implementierung dieser Strategie können Sie die Verwaltbarkeit von Protokollen, Spannen und Metriken verbessern und Ihr Überwachungs-Setup in ein auf bestimmte Teams zugeschnittenes Tool verwandeln. Dies verbessert die Verantwortlichkeit und Organisation und ermöglicht eine effektivere und effizientere Fehlerbehebung und Leistungsanalyse in Ihrer gesamten Anwendung.
DomainTagsService
direkt in den Jobimplementierungen sicher, dass die domänenspezifische Überwachung weiterhin aufrechterhalten werden kann.Definieren Sie Domänen und Teams
Das wird sich mit der Lib ändern!!!
Erstellen Sie Enumerationen, die verschiedene Domänen und Teams in Ihrer Anwendung darstellen:
@Domain
ist eine Annotation, die auf Klassen oder Funktionen angewendet werden kann und sie mit einem bestimmten Domänenwert kennzeichnet.DomainValue
ist eine Aufzählung, die verschiedene Domänen darstellt, die jeweils einem Team zugeordnet sind.Team
ist eine Aufzählung, die die verschiedenen Teams darstellt, die an der Anwendung arbeiten. @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) annotation class Domain(val value: DomainValue) enum class DomainValue(val team: Team) { USER_MANAGEMENT(Team.TEAM_A), PAYMENT_PROCESSING(Team.TEAM_B), NOTIFICATIONS(Team.TEAM_C) } enum class Team { TEAM_A, TEAM_B, TEAM_C }
Kommentieren Sie Klassen (und Methoden, falls erforderlich)
@Domain(DomainValue.USER_MANAGEMENT) class UserService { @Domain(DomainValue.PAYMENT_PROCESSING) fun processPayment() { ... } }
Behandeln nicht unterstützter Fälle
In Fällen, die nicht direkt kommentiert werden können, verwenden Sie DomainTagsService
direkt, um die Logik zu umschließen
fun executeNotSupportedByAnnotationsLogic() { domainTagsService.invoke(domain) { executeLogic() } }
Überwachen mit Datadog
Verwenden Sie künstliche Servicefilter für Monitore, Dashboards und APM-Traces-Filterung
Wenn Sie diese Schritte befolgen, können Sie Domänenanmerkungen effektiv in Ihrer monolithischen Anwendung implementieren und so eine verbesserte Überwachung, Verantwortlichkeit und Gesamteffizienz sicherstellen.