Schreiben eines Microservice-Blogs - Teil 1 „Allgemeine Beschreibung“

In diesem Artikel möchte ich unsere Erfahrungen mit SergeyMaslov zur Lösung typischer Probleme mithilfe der Microservice-Architektur am Beispiel der Aufgabe "Blog erstellen" teilen (in der Hoffnung, dass sich der Leser vorstellen kann, wie das Blog angeordnet ist, und dies sollte keine Fragen zur Funktionalität aufwerfen :)

Unser Blog wird also aus 5 in Golang geschriebenen Microservices bestehen:

  • Gateway-API (api-gw) - verantwortlich für das Routing, die Authentifizierung, die Protokollierung und die Verfolgung von Anforderungen
  • Benutzer (Benutzer) - Registrierung / Authentifizierung von Benutzern, Protokollierung, Verfolgung von Anforderungen
  • Artikel (Post) - Erstellen / Lesen / Ändern / Löschen von Artikeln (CRUD), Protokollieren, Nachverfolgen und Autorisieren von Anforderungen
  • Kommentare - Erstellen / Lesen / Ändern / Löschen von Kommentaren (CRUD), Protokollieren, Nachverfolgen und Autorisieren von Anforderungen
  • Kategorien (Kategorie) - Erstellen / Lesen / Ändern / Löschen von Kategorien (CRUD), Protokollieren, Nachverfolgen und Autorisieren von Anforderungen

Die Client-Anwendung (Web / Frontend) wird auf vue.js implementiert und interagiert mit Microservices über die REST-API, und die Microservices selbst interagieren über gRPC miteinander.

Als Speicher verwenden wir MongoDB.

Wir werden mit einer separaten Kirsche auf dem Kuchen zeigen, wie die API-Dokumentation (im Swagger-Format) in einem sich aktiv entwickelnden Projekt mit minimalem Arbeitsaufwand auf dem neuesten Stand gehalten werden kann.

Blog-Komponentendiagramm


Bild

Jeder Microservice wird in einem separaten Docker-Container implementiert und das Projekt mit Docker-Compose gestartet.

Machen Sie sofort eine Reservierung im Beispiel, um den Entwicklungsprozess zu vereinfachen. Ich werde zwei Annahmen verwenden, die in der Produktion nicht verwendet werden sollten.

  • Die Datenbank wird in einem Docker-Container bereitgestellt. Dieser Ansatz verringert die Speicherzuverlässigkeit (mit Ausnahme des bei HighLoad 2018 diskutierten Schemas).
  • Das gesamte Projekt wird in einem Git-Repository gehostet. Dieser Ansatz widerspricht einem der Grundprinzipien der Microservice-Architektur - der Isolation - und erhöht die Wahrscheinlichkeit einer Konnektivität zwischen Komponenten.

Sie können die Demo des Projekts hier und den Quellcode hier sehen .

Projektstruktur




Wie der Entwicklungsprozess aufgebaut wird


Wie ich bereits sagte, wird die Interaktion zwischen Microservices auf gRPC basieren. Kurz gesagt, gRPC ist ein von Google entwickeltes Hochleistungsframework zum Aufrufen von Remoteprozeduren (RPC) - es funktioniert zusätzlich zu HTTP / 2. GRPC basiert auf dem sogenannten Protofile (siehe Beispiel unten), dessen Hauptaufgabe darin besteht, zwei Dinge in kompakter Form zu deklarieren:

  • Geben Sie eine vollständige Liste der Dienstschnittstellen an (analog zu API-Schnittstellen).
  • Beschreiben Sie, was dem Eingang jeder Schnittstelle zugeführt wird und was wir am Ausgang erhalten.

Im Folgenden wird als Beispiel das Protofile des Kategoriedienstes angegeben.

syntax = "proto3"; package protobuf; import "google/api/annotations.proto"; //   Category service CategoryService { //  rpc Create (CreateCategoryRequest) returns (CreateCategoryResponse) { option (google.api.http) = { post: "/api/v1/category" }; } //  rpc Update (UpdateCategoryRequest) returns (UpdateCategoryResponse) { option (google.api.http) = { post: "/api/v1/category/{Slug}" }; } //  rpc Delete (DeleteCategoryRequest) returns (DeleteCategoryResponse) { option (google.api.http) = { delete: "/api/v1/category/{Slug}" }; } //   SLUG rpc Get (GetCategoryRequest) returns (GetCategoryResponse) { option (google.api.http) = { get: "/api/v1/category/{Slug}" }; } // rpc Find (FindCategoryRequest) returns (FindCategoryResponse) { option (google.api.http) = { get: "/api/v1/category" }; } } //------------------------------------------ // CREATE //------------------------------------------ message CreateCategoryRequest { string ParentId = 1; string Name = 2; string Path = 3; } message CreateCategoryResponse { Category Category = 1; } //------------------------------------------ // UPDATE //------------------------------------------ message UpdateCategoryRequest { string Slug = 1; string ParentId = 2; string Name = 4; string Path = 5; int32 Status = 6; } message UpdateCategoryResponse { int32 Status =1; } //------------------------------------------ // DELETE //------------------------------------------ message DeleteCategoryRequest { string Slug = 1; } message DeleteCategoryResponse { int32 Status =1; } //------------------------------------------ // GET //------------------------------------------ message GetCategoryRequest { string Slug = 1; } message GetCategoryResponse { Category Category = 1; } //------------------------------------------ // FIND //------------------------------------------ message FindCategoryRequest { string Slug = 1; } message FindCategoryResponse { repeated Category Categories = 1; } //------------------------------------------ // CATEGORY //------------------------------------------ message Category { string Slug = 1; string ParentId = 2; string Path = 3; string Name = 4; int32 Status = 5; } 

Nachdem wir nun allgemein herausgefunden haben, warum ein Protofile benötigt wird, wollen wir sehen, wie der Entwicklungsprozess unserer Microservices aussehen wird:

  1. Wir beschreiben die Struktur des Dienstes im Protofile;
  2. Wir starten den Codegenerator (./bin/protogen.sh), er generiert den Hauptteil des Servercodes für uns + er erstellt Clientcode, zum Beispiel für das API-Gateway + er erstellt eine aktuelle Dokumentation im Swagger-Format;
  3. Alles, was wir mit unseren eigenen Händen tun müssen, ist, den Code für die Implementierung der Schnittstellen in eine spezielle Datei /protobuf/functions.go zu schreiben.

Wenn wir Änderungen an einem unserer Microservices vornehmen möchten, gehen wir wie oben beschrieben vor: Wir bearbeiten das Protofile, führen Protogen aus, bearbeiten die Implementierung in functions.go und die Änderungen werden automatisch der Dokumentation und den Clients überlassen.

Fortsetzung im Artikel "Schreiben eines Blogs über Microservices Teil 2 der Gateway-API".

Source: https://habr.com/ru/post/de473514/


All Articles