Swift Microservices Architect
In einem auf andere Weise erstellten Backend behalte seine Struktur und Konventionen bei, es sei denn, der Benutzer bittet um Änderungen, und übernimm aus dieser Fähigkeit nur das, was dem Backend fehlt.
X steht für einen Dienst im Namen eines Ziels (LoansCore) und wofür ein Typ benannt ist (BorrowBookUseCase, LoanService); <Org> und <org> für die Organisation. Die Beispiele sind Bookshelf, eine kleine Leihbibliothek:
| Paket | Enthält |
|---|---|
bookshelf-identity | Konten, Passwörter, Sitzungen; stellt jedes Zugriffstoken aus; Rücksetzcodes in Valkey; Mitglieder für andere Dienste, intern |
bookshelf-catalog | Bücher: jeder liest, Administratoren bearbeiten; Loans schlägt Bücher intern nach |
bookshelf-loans | Die Ausleihen eines Mitglieds, eine Mandantentabelle; ein Workflow markiert eine Ausleihe als überfällig und sendet eine Benachrichtigung |
bookshelf-gateway | Die öffentliche HTTP-API, die an die gRPC-Verträge der Dienste weiterleitet |
bookshelf-core | BookshelfAuthentication, BookshelfPersistence, BookshelfTransport, BookshelfTesting |
bookshelf-protos | IdentityProtos, CatalogProtos, LoansProtos |
Die Form
Clients ── HTTPS ──► edge (TLS endet) ── HTTP ──► Gateway (Hummingbird, OpenAPI)
Gateway ── gRPC, mTLS, das JWT des Aufrufers ──► XService jedes Dienstes
Service, Worker ── gRPC, mTLS ──► XInternalService eines anderen Dienstes
Service, Worker ── mTLS ──► Temporal Service ──► seine eigene Postgres-Datenbank, Valkey
Jeder Dienst und das Gateway hängen von <org>-core, <org>-protos und den swift-microservices-Bibliotheken ab (Stack).
Das Paket eines Dienstes
<org>-x
├── XCore Domain-Modelle, Fehler, Repository-Protokolle und -Befehle, Ports, Use Cases
├── XPostgres ein Scope pro Datenbankrolle, Repositories, Anweisungen, Migrationen
├── XGRPC XService und XInternalService, Protobuf-Konvertierungen, gRPC-Clients für die Ports von Core
├── XTemporal Workflows, Activity-Container, der Temporal-Client für den Workflow-Port von Core
├── XValkey Repositories für kurzlebige Werte
├── X<Provider> eine Drittanbieter-API hinter einem Core-Port (LoansResend)
└── X Ausführbare Datei: Befehle, Konfigurationsstandards, Migrationen, Kompositionswurzeln
Ein Dienst hat nur die Ziele, die er benötigt, und jedes importiert nur das, was seine Zeile auflistet. Harte Regeln:
- XCore importiert keinen Treiber, kein Transportmittel, keinen Vertrag, keine Workflow-Engine, kein Konfigurations- oder Lebenszyklusmodul (was Core linken darf).
- Adapter-Ziele importieren sich niemals gegenseitig; die ausführbare Datei reicht eines durch die Protokolle von Core an das andere weiter.
- Generierte Vertragstypen verlassen niemals XGRPC, das HTTP-Ziel des Gateways und ausführbare Dateien.
- Nur eine ausführbare Datei liest Konfiguration, erstellt Clients und führt die
ServiceGroupaus. - Kein Dienst liest die Datenbank eines anderen; Daten überqueren Dienste nur durch Verträge.
Wer besitzt was
| Belang | Besitzer |
|---|---|
| Geschäftsregeln, Autorisierungsentscheidungen, was ein Fehler bedeutet | Der Use Case in XCore; Adapter konvertieren und delegieren nur |
| Was ein Dienst über die Daten eines anderen weiß | Ein Modell in seinem XCore Ports/, neben dem Port, der es zurückgibt |
| Protobuf ↔ Domain, HTTP ↔ protobuf | Die Protobuf/-Konvertierungen von XGRPC; die Schemas/ des Gateways |
| Nachrichten zwischen Prozessen; die öffentliche API | <org>-protos; die openapi.yaml des Gateways |
| Wer der Aufrufer ist | Das Gateway verifiziert und leitet das Token weiter; jeder Dienst verifiziert es erneut |
| Welche Prozesse ein internes RPC aufrufen dürfen | mTLS am Listener: jeder Prozess, den die Zertifizierungsstelle der Umgebung signiert |
| Mandantentrennung | Zeilenbasierte Sicherheit; <Org>Persistence bindet den Aufrufer an jede Transaktion, und die Use Cases jeder Zielgruppe laufen als ihre Datenbankrolle |
| Dauerhafte, verzögerte oder dienstübergreifende Arbeit | Ein Temporal-Workflow in XTemporal |
| Was jeder Dienst identisch benötigt | <org>-core: Identität, Mandantenbindung, Transport-Reader |
Codestil
Code liest sich wie die Anforderung, die er implementiert, mit Apples WWDC-Beispielcode als Maßstab (Stil). Use Cases und Adapter bilden Fehler auf diese Weise ab:
do {
… // die Arbeit, in der Reihenfolge, die die Anforderung angibt
} catch let error as BorrowBookUseCaseError {
throw error
} catch CatalogClientError.unavailable {
logger.warning("Ausleihe fehlgeschlagen: der Katalog ist nicht verfügbar")
throw .catalogUnavailable
} catch {
logger.error("Ausleihe fehlgeschlagen: unbekannter Fehler", metadata: ["error": "\(String(reflecting: error))"])
throw .unknown
}
- Ein
doenthält die Arbeit bis zu ihremreturn, und jedescatchbeendet seinen eigenen Pfad: nichts wird vor demdodeklariert, damit eincatches füllt. - Bauen, dann aufrufen: Ein Wert, den ein Aufruf benötigt, ist ein benanntes
let, niemals eine Konvertierung,tryoderawaitin den Argumenten (bauen, dann aufrufen). - Keine Hilfsmethoden in Use Cases, Workflows oder Activities und kein
Result-Hantieren, Steuerungsflags,try?, verschachteltesdoin einemcatchoder Force-Unwraps. - Swift 6-Modus mit
ExistentialAny,MemberImportVisibility,InternalImportsByDefaultundNonisolatedNonsendingByDefault(Swift-Einstellungen);package-Zugriff über die Ziele eines Dienstes hinweg. - Alles, was eine Grenze überschreitet, ist
Sendable; keinTask {}oderTask.detached, und ungeprüfte Nebenläufigkeit nur dort, wo Nebenläufigkeit es erlaubt.
Fallstricke
- Eine Komponente, die aus der
ServiceGroupausgelassen wird, läuft nie: Ein nicht gestarteterGRPCClientoderPostgresClientverbindet sich nie, daher warten seine Aufrufe bis zu ihrer Frist. - Ein Prozess, der als Datenbankbesitzer verbunden ist, umgeht die zeilenbasierte Sicherheit, daher verbindet sich jeder Prozess als seine Rollen und nur
serve --migrate-databaseals Besitzer. - Temporal prüft
Codablenur zur Laufzeit: Jede Workflow- und Activity-Nutzlast und jeder Typ, den sie enthält, istCodable, Sendable(Workflows). - Workflow-Code wird wiederholt:
Date.now,UUID(), Zufallszahlen,Task.sleepoder jede E/A in einem Workflow zerstört ihn (Determinismus). - Ein einfaches oder eingeschränktes
import Foundationin eigenem Code verknüpft vollständiges Foundation unter Linux; verwende den bedingten ImportFoundationEssentials.
Checklisten
Kopiere die Checkliste der Aufgabe in die Antwort und hake die erledigten Punkte ab; jede darin genannte .md-Datei befindet sich in references/.
Ein Backend planen
- [ ] Die Fähigkeiten und die Daten, die jede besitzt; ein Dienst pro Fähigkeit (system.md#aufteilung-eines-systems-in-dienste)
- [ ] Jeden Dienst benennen; seine Zielnamen gegen jedes Modul im Graphen prüfen
- [ ] Pro Dienst: XService-RPCs nach Zielgruppe, XInternalService-RPCs und Aufrufer ohne Aufrufzyklen, Tabellen (Mandant oder nicht), Workflows, kurzlebiger Zustand
- [ ] Pro Dienst: seine Ziele, Befehle und Datenbankrollen
- [ ] Die Produkte von <org>-core, die Verträge von <org>-protos, die Routen des Gateways nach Stufe
- [ ] Build-Reihenfolge: <org>-core und <org>-protos, der Token-Aussteller, jeder Dienst vor seinen Aufrufern, das Gateway
- [ ] Den Plan aus system.md#der-plan schreiben; vor dem Code gegen die harten Regeln prüfen
Einen Dienst hinzufügen
- [ ] <org>-protos: XProtos mit XService und XInternalService, falls Prozesse hereinrufen
- [ ] Paket <org>-x aus packages.md#packageswift-template mit nur den Zielen, die der Plan nennt
- [ ] XCore: Modelle, Fehler, Repositories, Ports, ein Use Case pro RPC (use-cases.md)
- [ ] XPostgres: Rollen, Tabellen, zeilenbasierte Sicherheit, Anweisungen, ein Scope pro Rolle (persistence.md)
- [ ] XGRPC: Proto-Dienste über den Use Cases, Konvertierungen, Clients für Ports (grpc.md)
- [ ] XTemporal, XValkey, X<Provider> wie vom Plan benötigt
- [ ] X: Befehle, InMemoryProvider-Standardwerte, Migrationen, Serve und Run mit einem Worker (composition.md)
- [ ] Gateway: Routen für die öffentlichen RPCs (gateway.md)
- [ ] Ein Test-Ziel pro Modul über Mocks (testing.md)
- [ ] Seine CI-Workflows, Containerfile und Dependabot als Dienst (delivery.md)
- [ ] swift build und swift test; beheben und wiederholen, bis beide ohne Warnungen bestehen
Eine Operation hinzufügen
- [ ] Vertrag: das RPC unter seiner Zielgruppe in XService oder in XInternalService
- [ ] XCore: die fünf Dateien des Use Cases; sein Scope listet nur das auf, was es berührt (use-cases.md)
- [ ] XPostgres: die Scopes der Rollen, unter denen es laufen kann, übernehmen sein Scope-Protokoll
- [ ] XGRPC: der Handler und die Eingabekonvertierung, jeder Fehlerfall abgebildet
- [ ] Ausführbare Datei: der Use Case auf der Datenbank seiner Rolle, an den Dienst übergeben
- [ ] Gateway: die Route in seiner Stufe, falls öffentlich
- [ ] Tests: die Ergebnisse des Use Cases und die Statuscodes des Handlers, über Mocks
- [ ] swift build und swift test; beheben und wiederholen, bis beide ohne Warnungen bestehen
Einen dauerhaften Prozess hinzufügen
- [ ] XCore: der XWorkflowClient-Port; die Use Cases, deren Activities es ausführt, übernommen vom Worker-Scope
- [ ] XTemporal: der Workflow, seine Activities, TemporalXWorkflowClient, benannte ActivityOptions (workflows.md)
- [ ] Der Use Case, der ihn startet, nachdem seine Transaktion abgeschlossen ist, mit einer deterministischen ID
- [ ] Ausführbare Datei: der Temporal-Client in Serve; die Worker-Gruppe und ihre Run-Wurzel
- [ ] Tests: der Workflow auf dem zeitspringenden Server, seine Activities über Mocks
- [ ] swift build und swift test; beheben und wiederholen, bis beide ohne Warnungen bestehen
CI/CD einrichten
- [ ] Die Art des Pakets: öffentliche Bibliothek, Systembibliothek oder Dienst (delivery.md#paketarten)
- [ ] Seine CI-Workflows, die swift-microservices/ci bei einem Release-Commit aufrufen; dependabot.yml; .license_header_template und .licenseignore; die Geheimnisse
- [ ] Eine Bibliothek: die Semver-Labels und .github/release.yml; ein Dienst: sein Containerfile
- [ ] swift build und swift test mit den Flags von CI; beheben und wiederholen, bis beide bestehen
Ein Backend überprüfen
- [ ] Die Grenzprüfungen ausführen (packages.md#grenzen-prüfen)
- [ ] Jeder Use Case: seine fünf Dateien, typisierte Fehler, ein Catch pro Fall, keine Helfer, die richtige Datenbankrolle
- [ ] Jeder Adapter konvertiert und delegiert nur; jeder Fehlerfall ist abgebildet
- [ ] Jede Wurzel: Konfiguration nur dort gelesen, jede Komponente in der ServiceGroup in Abhängigkeitsreihenfolge
- [ ] Swift-Einstellungen, FoundationEssentials-Importe, Paketzugriff, Benennung (conventions.md)
- [ ] Ergebnisse, eingestuft als blockierend (Mandantentrennung, Autorisierung, Anmeldeinformationen, Build), schwerwiegend (die Formen), geringfügig (Benennung, Layout, Protokollierung), jede mit Angabe einer Datei und Zeile oder eines leeren Grep, mit der Regel und der Korrektur; dann die Entscheidungen des Benutzers. Code nur ändern, wenn darum gebeten wird
- [ ] swift build und swift test; jedes Ergebnis melden oder warum es nicht ausgeführt werden konnte
Referenzen
Lies die Referenz für den betreffenden Teil:
| Referenz | Deckt ab |
|---|---|
| system.md | Aufteilung in Dienste, Verträge, wie Dienste kommunizieren, die gemeinsamen Pakete, der Plan |
| packages.md | Ziele und ihre Importe, Package.swift, Swift-Einstellungen, Traits und Foundation, Layouts, Grenzprüfungen |
| stack.md | Die Bibliotheken, welches Ziel welche verknüpft, Foundation-Verknüpfung, Auswahl von Versionen |
| use-cases.md | Modelle, Fehler, Repositories, Ports, die fünf Dateien eines Use Cases und sein Körper, Transaktionen, Autorisierung |
| persistence.md | Scopes pro Datenbankrolle, zeilenbasierte Sicherheit, Anweisungen, Migrationen, Valkey |
| grpc.md | Verträge, Proto-Dienste, Handler, Konvertierungen, Paginierung, Statuscodes, Clients, Transporte |
| gateway.md | OpenAPI-Typen, Anforderungskontexte und -stufen, Controller, Webhooks, Fehler, Upstream-Clients |
| workflows.md | Starten von Workflows, Nutzlasten, Determinismus, Activities und Optionen, Versionen, der Worker |
| composition.md | Befehle, Kompositionswurzeln, Konfiguration, Protokollierung, die ServiceGroup |
| security.md | Das Vertrauensmodell, mTLS, Benutzertoken, Autorisierungsebenen, Geheimnisse, Webhooks |
| style.md | Wie der Code liest: Fehler, Nebenläufigkeit, Importe, Foundation, Typen, Formatierung |
| testing.md | Test-Ziele, was jedes beweist, Mocks |
| delivery.md | CI-Workflows pro Paketart, Veröffentlichungen, Bereitstellung, das Containerfile, Dependabot |
| conventions.md | Benennung eines Pakets, Ziels, Typs, einer Datei, eines Schlüssels oder Ordners |
Verwandte Fähigkeiten
Für den Code innerhalb der Formen lade diese, wenn sie installiert sind; wo diese Fähigkeit eine Form angibt, folge ihr:
- Akteure, Aufgabengruppen, Abbruch,
Sendable-Diagnosen, Swift 6-Migration:swift-concurrency - Argumentlabels, Methodennamen, Dokumentationskommentare:
swift-api-design-guidelines - Tests von Use Cases, Handlern und Workflows:
swift-testing-expert