Warum müssen Sie möglicherweise die Amazon-Webdienstinfrastruktur emulieren?
Zuallererst spart es - spart Zeit für Entwicklung und Debugging und was ebenso wichtig ist - spart Geld aus dem Projektbudget. Es ist klar, dass der Emulator nicht zu 100% mit der ursprünglichen Umgebung identisch ist, die wir emulieren möchten. Um jedoch die Entwicklung und Automatisierung des Prozesses zu beschleunigen, sollten die vorhandenen Ähnlichkeiten ausreichen. Das aktuellste Ereignis im Jahr 2018 mit AWS war die Sperrung der IP-Adressen von AWS-Subnetzen in Russland durch IP-Anbieter. Diese Sperren wirkten sich auf unsere Infrastruktur in der Amazon Cloud aus. Wenn Sie die AWS-Technologie verwenden und das Projekt in dieser Cloud platzieren möchten, zahlt sich die Emulation für Entwicklung und Test mehr als aus.

In der Veröffentlichung werde ich Ihnen erklären, wie wir es geschafft haben, einen solchen Trick mit den Diensten S3, SQS, RDS PostgreSQL und Redshift zu erreichen, als wir ein vorhandenes Data Warehouse über viele Jahre auf AWS migriert haben.
Dies ist nur ein Teil meines letztjährigen
Meetings auf der
Karte , das den Themen von AWS- und Java-Hubs entspricht. Der zweite Teil bezieht sich auf PostgreSQL-, Redshift- und Spaltendatenbanken. Die Textversion kann in den entsprechenden Hubs veröffentlicht werden. Videos und Folien befinden sich auf
der Konferenzwebsite .
Bei der Entwicklung einer Anwendung für AWS während des Blockierens von AWS-Subnetzen hat das Team diese bei der täglichen Entwicklung neuer Funktionen praktisch nicht bemerkt. Tests haben auch funktioniert und Sie können die Anwendung debuggen. Und nur beim Versuch, die Anwendungsprotokolle in Logentries zu betrachten, wurden Metriken in SignalFX oder Datenanalysen in Redshift / PostgreSQL RDS enttäuscht - die Dienste waren nicht über das Netzwerk des russischen Anbieters verfügbar. Die AWS-Emulation hat uns dabei geholfen, dies nicht zu bemerken und viel größere Verzögerungen bei der Arbeit mit der Amazon Cloud über ein VPN-Netzwerk zu vermeiden.
Jeder Cloud-Anbieter „unter der Haube“ hat viele Drachen und Sie sollten sich nicht der Werbung hingeben. Sie müssen verstehen, warum dies alles für den Dienstanbieter erforderlich ist. Natürlich hat die vorhandene Infrastruktur von Amazon, Microsoft und Google Vorteile. Und wenn sie Ihnen sagen, dass alles nur getan wird, um Ihnen die Entwicklung zu erleichtern, versuchen sie höchstwahrscheinlich, Sie auf Ihre Nadel zu setzen und die erste Dosis kostenlos zu geben. Damit sie später nicht von der Infrastruktur und der spezifischen Technologie abkommen. Daher werden wir versuchen, eine Lieferantenbindung zu vermeiden. Es ist klar, dass es nicht immer möglich ist, von bestimmten Entscheidungen vollständig zu abstrahieren, und ich denke, dass es ziemlich oft möglich ist, fast 90% in einem Projekt zu abstrahieren. Die verbleibenden 10% des Projekts, die an einen Anbieter von Technologien gebunden sind, die sehr wichtig sind, optimieren entweder die Anwendungsleistung oder die einzigartigen Funktionen, die es sonst nirgendwo gibt. Sie sollten sich immer an die Vor- und Nachteile von Technologien erinnern und sich so gut wie möglich schützen und sich nicht auf eine bestimmte API eines Cloud-Infrastrukturanbieters "setzen".
Amazon schreibt über die
Nachrichtenverarbeitung auf seiner Website. Das Wesen und die Abstraktion von Nachrichtenaustauschtechnologien sind überall gleich, obwohl es Nuancen gibt - Nachrichten, die durch Warteschlangen oder durch Themen geleitet werden. Daher empfiehlt AWS die Verwendung des bereitgestellten und verwalteten Apache ActiveMQ zum Migrieren von Anwendungen von einem vorhandenen Messaging-Broker und für neue Amazon SQS / SNS-Anwendungen. Dies ist ein Beispiel für die Bindung an die eigene API anstelle der standardisierten JMS-API und der Protokolle AMQP, MMQT, STOMP. Es ist klar, dass dieser Anbieter mit seiner Lösung möglicherweise eine höhere Leistung aufweist, Skalierbarkeit unterstützt usw. Wenn Sie aus meiner Sicht ihre Bibliotheken und keine standardisierten APIs verwenden, gibt es viel mehr Probleme.
AWS verfügt über eine Redshift-Datenbank. Es ist eine verteilte Datenbank mit einer massiven parallelen Architektur. Sie können eine große Menge Ihrer Daten in Tabellen auf mehreren Redshft-Sites in Amazon hochladen und analytische Abfragen für große Datenmengen durchführen. Dies ist kein OLTP-System, bei dem es wichtig ist, dass Sie kleine Anforderungen für eine kleine Anzahl von Datensätzen häufig genug mit ACID-Garantien ausführen. Bei der Arbeit mit Redshift wird davon ausgegangen, dass Sie nicht viele Abfragen pro Zeiteinheit haben, diese jedoch Aggregate für eine sehr große Datenmenge lesen können. Dieses System wird vom Anbieter so positioniert
, dass Ihr Data Warehouse (Warehouse) auf AWS
aktualisiert wird und ein einfaches Laden der Daten versprochen wird. Welches ist überhaupt nicht wahr.
Ein Auszug aus der Dokumentation darüber, welche
Typen Amazon Redshift
unterstützt . Es ist ein eher dürftiger Satz, und wenn Sie etwas zum Speichern und Verarbeiten von Daten benötigen, die hier nicht aufgeführt sind, wird es für Sie schwierig sein, zu arbeiten. Zum Beispiel eine GUID.
Frage aus der Halle: "Und JSON?"
- JSON kann nur als VARCHAR geschrieben werden und es gibt verschiedene Funktionen für die Arbeit mit JSON.
Kommentar des Publikums: "Postgres hat normale JSON-Unterstützung."
- Ja, es unterstützt diese Art von Daten und Funktionen.
Redshift basiert jedoch auf PostgreSQL 8.0.2. Es gab ein ParAccel-Projekt. Wenn ich mich nicht irre, ist diese Technologie von 2005 eine Abzweigung von Postgres, die einen Scheduler für verteilte Anforderungen hat, der auf einer massiv parallelen Architektur basiert. 5-6 Jahre vergingen und dieses Projekt wurde für die Amazon Web Servces-Plattform lizenziert und Redshift genannt. Etwas wurde aus dem ursprünglichen Postgres entfernt, viel wurde hinzugefügt. Sie fügten hinzu, dass im Zusammenhang mit der Authentifizierung / Autorisierung in AWS mit Rollen die Sicherheit in Amazon einwandfrei funktioniert. Wenn Sie beispielsweise eine Verbindung von Redshift zu einer anderen Datenbank mithilfe einer fremden Datenquelle herstellen müssen, werden Sie diese nicht finden. Es gibt keine Funktionen für die Arbeit mit XML, Funktionen für die zweimalige Arbeit mit JSON, die falsch berechnet wurden.
Versuchen Sie beim Entwickeln einer Anwendung, sich
nicht auf bestimmte Implementierungen zu verlassen, und der Anwendungscode hängt nur von Abstraktionen ab. Sie können diese Fassaden und Abstraktionen selbst erstellen, aber in diesem Fall gibt es viele vorgefertigte Bibliotheken - Fassaden. Welche den Code von bestimmten Implementierungen, von bestimmten Frameworks abstrahieren. Es ist klar, dass sie möglicherweise nicht alle Funktionen als „gemeinsamer Nenner“ für Technologien unterstützen. Es ist besser, Software zu entwickeln, die auf Abstraktionen basiert, um das Testen zu vereinfachen.
Um AWS zu emulieren, werde ich zwei Optionen erwähnen. Das erste ist ehrlicher und korrekter, aber es funktioniert langsamer. Der zweite ist schmutzig und schnell. Ich erzähle Ihnen von der Hack-Option - wir versuchen, die gesamte Infrastruktur in einem Prozess zu erstellen - die Tests und die plattformübergreifende Option funktionieren schneller bei der Arbeit unter Windows (wo Docker nicht immer Geld mit Ihnen verdienen kann).
Die erste Methode ist perfekt, wenn Sie unter Linux / Macos entwickeln und Docker haben. Es ist besser,
atlassian localstack zu verwenden . Es ist praktisch,
Testcontainer zu verwenden, um localstack in die JVM zu integrieren.
Was mich davon abgehalten hat, Lockalstack in Docker für das Projekt zu verwenden, war, dass die Entwicklung unter Windows erfolgte und niemand für die Alpha-Version von Docker bürgte, als dieses Projekt gestartet wurde ... Es ist auch möglich, dass sie in keinem Unternehmen, das es ernst meint, eine virtuelle Maschine mit Linux und Docker installieren dürfen zur Informationssicherheit. Ich spreche nicht davon, in einer sicheren Umgebung in Investmentbanken zu arbeiten und fast alle Verkehrsfirewalls dort zu verbieten.
Betrachten wir Optionen zum Emulieren von Simple Storage S3. Dies ist kein gewöhnliches Amazon-Dateisystem, sondern ein verteilter Objektspeicher. In dem Sie Ihre Daten als BLOB ablegen, ohne die Möglichkeit der Änderung und Hinzufügung von Daten. Es gibt ähnliche vollwertige verteilte Lager anderer Hersteller. Mit dem verteilten Ceph-Objektspeicher können Sie beispielsweise mit seiner Funktionalität mithilfe des
S3-REST-Protokolls und des vorhandenen Clients mit minimalen Änderungen arbeiten. Dies ist jedoch eine ziemlich schwere Lösung für die Entwicklung und das Testen von Java-Anwendungen.
Ein schnelleres und geeigneteres Projekt ist die Java-Bibliothek
s3proxy . Es emuliert das S3-REST-Protokoll und übersetzt es in die entsprechenden
jcloud- API-Aufrufe.
Außerdem können Sie viele Implementierungen zum echten Lesen und Speichern von Daten verwenden. Es kann Anrufe an die Google App Engine-API, die Microsoft Azure-API, senden. Für Tests ist es jedoch bequemer, jcloud-Transientenspeicher im RAM zu verwenden. Es ist auch erforderlich, die Version des Authentifizierungsprotokolls AWS S3 zu konfigurieren und die Schlüssel- und Geheimwerte anzugeben. Außerdem muss der Endpunkt konfiguriert werden - der Port und die Schnittstelle, die dieser S3-Proxy überwacht. Dementsprechend sollte Ihr Code, der den AWS SDK-Client verwendet, in Tests mit dem S3 AWS-Endpunkt und nicht mit der AWS-Region verbunden werden. Denken Sie auch hier daran, dass s3proxy nicht alle Funktionen der S3-API unterstützt, aber alle unsere Verwendungsszenarien perfekt emulieren! Selbst das mehrteilige Hochladen großer Dateien wird von s3proxy unterstützt.
Amazon Simple Queue Service ist ein Warteschlangendienst. Es gibt einen
Elasticmq- Warteschlangendienst, der in Scala geschrieben ist und Ihrer Anwendung mithilfe des Amazon SQS-Protokolls präsentiert werden kann. Ich habe es im Projekt nicht verwendet, daher werde ich den Initialisierungscode geben und den Informationen der Entwickler vertrauen.
Im Projekt bin ich in die andere Richtung gegangen und der Code hängt von den Spring-JMS-Abstraktionen von JmsTemplate und JmsListener ab. Die Projektabhängigkeiten geben den JMS-Treiber für SQS com.amazonaws an: amazon-sqs-java-messaging-lib. Dies betrifft den Hauptanwendungscode.
In Tests verbinden wir Artemis-jms-server als eingebetteten JMS-Server für Tests, und im Test Spring-Kontext verwenden wir anstelle der SQS-Verbindungsfactory die Artemis-Verbindungsfactory. Artemis ist die nächste Version von Apache ActiveMQ, einer vollwertigen, modernen Message Oriented Middleware - nicht nur eine Testlösung. Vielleicht werden wir in Zukunft nicht nur in Autotests eingesetzt. Durch die Verwendung von JMS-Abstraktionen in Verbindung mit Spring haben wir sowohl den Anwendungscode als auch die Möglichkeit zum einfachen Testen vereinfacht. Sie müssen nur die Abhängigkeiten org.springframework.boot: spring-boot-startup-artemis und org.apache.activemq: artemis-jms-server hinzufügen.
In einigen Tests kann PostgreSQL emuliert werden, indem es durch
H2Database ersetzt wird . Dies funktioniert, wenn die Tests nicht akzeptiert werden und keine spezifischen PG-Funktionen verwenden. Gleichzeitig kann H2 eine Teilmenge des PostgreSQL-Wire-Protokolls ohne Unterstützung für Datentypen und Funktionen emulieren. In unserem Projekt verwenden wir Foreing Data Wrapper, daher funktioniert diese Methode bei uns nicht.
Sie können echtes PostgreSQL ausführen.
postgresql-embedded lädt die eigentliche Distribution bzw. das Archiv mit Binärdateien für die Plattform, auf der wir laufen, herunter und entpackt sie. Unter Linux unter tempfs im RAM und unter Windows in% TEMP% wird der Postgresql-Serverprozess gestartet, die Servereinstellungen und Datenbankparameter werden konfiguriert. Aufgrund der Distributionsverteilungsfunktionen funktionieren ältere Versionen als PG 11 unter Linux nicht. Für mich selbst habe ich eine
Wrapper-Bibliothek erstellt , mit der Sie PostgreSQL-Binärassemblys nicht nur von einem HTTP-Server, sondern auch vom Maven-Repository abrufen können. Dies kann sehr nützlich sein, wenn Sie in isolierten Netzwerken arbeiten und auf einem CI-Server ohne Internetzugang aufbauen. Ein weiterer Vorteil bei der Arbeit mit meinem Wrapper ist die Annotation der CDI-Komponente, wodurch die Verwendung der Komponente beispielsweise im Spring-Kontext vereinfacht wird. Die Implementierung der AutoClosable-Serverschnittstelle erfolgte früher als im ursprünglichen Projekt. Sie müssen nicht daran denken, den Server zu stoppen. Er wird gestoppt, wenn der Spring-Kontext automatisch geschlossen wird.
Beim Start können Sie eine Datenbank basierend auf Skripten erstellen und den Spring-Kontext durch entsprechende Eigenschaften ergänzen. Wir erstellen jetzt ein Datenbankschema mithilfe von
Flyway- Skripten, um das Datenbankschema zu migrieren.
Diese werden jedes Mal gestartet, wenn die Datenbank in Tests erstellt wird.
Um die Daten nach dem Ausführen der Tests zu überprüfen, verwenden wir die Bibliothek spring-test-dbunit. In Anmerkungen zu den Testmethoden geben wir an, mit welchen Uploads der Status der Datenbank verglichen werden soll. Dadurch müssen Sie keinen Code schreiben, um mit dbunit arbeiten zu können. Sie müssen lediglich den Bibliothekslistener zum Testcode hinzufügen. Sie können angeben, in welcher Reihenfolge die Daten aus den Tabellen nach Abschluss der Testmethode gelöscht werden, wenn der Datenbankkontext zwischen den Tests wiederverwendet wird. Im Jahr 2019 gibt es einen moderneren Ansatz für
Datenbankfahrer , der mit junit5 arbeitet. Ein Anwendungsbeispiel sehen Sie beispielsweise
hier .
Das Schwierigste war, Amazon Redshift zu emulieren. Es gibt ein
Redshift-Fake-Driver- Projekt. Das Projekt konzentriert sich auf die Emulation des Ladens von Batchdaten in die Analysedatenbank von AWS. Im Protokollemulator jdbc: postgresqlredshift sind die Befehle COPY, UNLOAD implementiert, alle anderen Befehle werden an den regulären JDBC-PostgreSQL-Treiber delegiert.
Daher funktionieren die Tests nicht auf die gleiche Weise wie in Redshift, der Aktualisierungsoperation, bei der eine andere Tabelle als Datenquelle für die Aktualisierung verwendet wird (die Syntax unterscheidet sich in Redshift und PostgreSQL 9+. Ich habe auch eine unterschiedliche Interpretation des Zeilenzitats in SQL-Befehlen zwischen diesen Datenbanken festgestellt.
Aufgrund der Architektur einer echten Redshift-Datenbank ist das Einfügen, Aktualisieren und Löschen von Daten in Bezug auf E / A ziemlich langsam und „teuer“. Es ist möglich, Daten mit akzeptabler Leistung nur in großen "Paketen" einzufügen, und mit dem Befehl COPY können Sie nur Daten aus einem verteilten S3-Dateisystem herunterladen. Dieser Befehl in der Datenbank unterstützt verschiedene Datenformate AVRO, CSV, JSON, Parkett, ORC und TXT. Das Emulatorprojekt konzentriert sich auf CSV, TXT, JSON.
Um Redshift in den Tests zu emulieren, müssen Sie die PostgreSQL-Datenbank wie zuvor beschrieben starten und die Emulation des S3-Repositorys ausführen. Wenn Sie eine Verbindung zum Postgres herstellen, müssen Sie lediglich den Redshift-Fake-Treiber im Klassenpfad hinzufügen und die Treiberklasse jp.ne.opt.redshiftfake.postgres angeben. FakePostgresqlDriver. Danach können Sie das Datenbankschema auf demselben Flyway migrieren, und dbunit ist bereits mit dem Vergleichen von Daten nach dem Ausführen der Tests vertraut.
Ich frage mich, wie viele Leser AWS und Redshift in ihrer Arbeit verwenden. Schreiben Sie in den Kommentaren über Ihre Erfahrungen.
Mit nur Open Source-Projekten konnte das Team die Entwicklung in der AWS-Umgebung beschleunigen, Geld aus dem Projektbudget sparen und das Team nicht daran hindern, zu arbeiten, wenn AWS-Subnetze von Roskomnadzor blockiert wurden.