Dart-Service: Einführung, Backend-Infrastruktur

Inhaltsverzeichnis
1.

2. Backend

2.1. .

2.2. . SSL.

2.3. Dart.



3. Web

3.1. «Under construction»



4. Mobile





Einführung



Als Flutter-Entwickler fragen mich Bekannte oft: "Was ist die Dart-Sprache?" Sie schütteln den Kopf mit den Worten: "Aber Petja schreibt ernsthafte Transporte in Java, und in Yandex gibt es im Allgemeinen Pluspunkte im Verkauf ...". Nun, vielleicht ist Dart wirklich weit entfernt von der Praxis von " Fabriken zum Erstellen von Fabriken " aus Java. Wenn die Aufgabe jedoch darin besteht, Clientanwendungen für mehrere Plattformen gleichzeitig zu implementieren, ohne im Strom von Aufgaben zu ertrinken, um Entwickler verschiedener Zielbetriebssysteme zu synchronisieren. eine kohärente Benutzeroberfläche zu erstellen, die erkennbar, aber spezifisch für Android, iOS und das Web ist und im Allgemeinen ein angemessenes Budget und einen angemessenen Zeitrahmen einhält - hier hat Flutter keine Konkurrenten. Und diese Fragen sind doppelt wichtig, wenn Sie ... ein Startup haben.



Also die Legende: Ein bestimmtes Startup hat beschlossen, einen neuen Dienst zu erstellen ... zum Beispiel für
Einkaufslisten teilen
, , ToDo , :)

zwischen Dienstnutzern. Das Ziel des Starts ist es, ein MVP in drei Monaten auf drei Plattformen zu veröffentlichen (und der vierte ist natürlich der Server).



Vor 10 Jahren würde ich sagen, dass dieser Fall keine Lösung hat und würde versuchen, sich davon fernzuhalten. Vor 3 Jahren könnte der ReactNative / React / NodeJs-Stack die Lösung werden, im Jahr 2020 gibt es Dart dafür. Willkommen in der Atmosphäre der Entwicklung der Alpha-Version des Dienstes. Ich werde versuchen, den gesamten Entwicklungsprozess visuell durchzugehen und zu erklären. Der Code aller Anwendungen wird veröffentlicht. Kommentare, einschließlich Skizzen und Holivars, sind willkommen. Sie können den Autor "in der Sache" fragen oder einfach im Telegrammkanal unserer Abteilung um Rat fragen .







Backend-Infrastruktur



Die typische Art, eine Serveranwendung zu hosten, ist natürlich ein VPS (Virtual Private Server). Tatsächlich ist dies ein Teil eines physischen Servers in einem Rechenzentrum, dessen Ressourcen (Prozessorkerne und RAM) mithilfe der Virtualisierungstechnologie getrennt werden ( Informationen zu den gängigsten Hardwarevirtualisierungstechnologien finden Sie hier XEN , KVM ). Achtung: Software-Virtualisierungstechnologien ( OpenVZ , Virtuozzo ) sind aufgrund von Konflikten mit Docker und aggressivem Überverkauf möglicherweise nicht für unsere Aufgabe geeignet(Wenn Sie den Mietvertrag für einen solchen VPS sorgfältig lesen, werden Sie häufig feststellen, dass die Anbieter eine Auslastung des gemieteten Prozessorkerns von "mindestens 5%" (!) Garantieren. Dies bedeutet, dass der Anbieter plant, unseren Prozessorkern 20 (!) Mal zu verkaufen.)



Lassen Sie uns also ein Budget-VPS mit den folgenden Eigenschaften erhalten: 1 Prozessorkern, 1 GB RAM, 10 GB Speicher (in meinem Fall ist dies eine Hybrid-Festplatte). Wählen wir Ubuntu als Betriebssystem, vorzugsweise eine der LTS- Versionen. Danach erhält eine E-Mail eine Nachricht über die Serveraktivierung mit einem Login und einem Passwort für den SSH- Zugriff (verschlüsselter Zugriff auf die Betriebssystemkonsole unseres VPS) im SSH-Format:



IP-Adresse: 91.230.60.120

Benutzer: root

Passwort: <Passwort>



Lassen Sie uns die Verbindung überprüfen, indem Sie in die Befehlszeile eingeben:



ssh root@91.230.60.120


und auf Anfrage:



password: <>


Das Ergebnis sollte die Ausgabe von Informationen über den virtuellen Server und das Eingabefeld unten sein:



Server wird von xxxxxxxxxx gehostet



Hostname: 91.230.60.120

Kernel: 3.19.0-22-generic (Ubuntu xx.xx LTS)

Betriebszeit: 09:07:06 bis 3 Tage, 17:17, 1 Benutzer,

Lastdurchschnitt : 0,00, 0,01, 0,05 CPU: Intel® Xeon® CPU 0 @ 2,00 GHz (1 Kerne)

Speicher: 989 MB insgesamt / 723 MB frei



root@91.230.60.120: ~ $



Herzlichen Glückwunsch, unsere Der virtuelle Server wird erstellt und steht für die Arbeit zur Verfügung.



Definieren wir nun die Backend-Struktur. Wir brauchen einen HTTP-Server. Wir werden NGINX verwenden . Seine Aufgaben werden sein:



  1. Bereitstellen statischer Dateien (Webanwendungsdateien).
  2. Verteilung von Serviceressourcen, z. B. Dateien zum Nachweis des Domänenbesitzes für mobile Anwendungen, Informationen zum Eigentümer für den Erhalt von SSL-Zertifikaten Verschlüsseln usw.
  3. Reverse Proxy für den Zugriff auf Serveranwendungen.
  4. Verschlüsselung von Verbindungen - https.


Zwei Serveranwendungen:



  1. Benutzerregistrierungs- und Autorisierungsantrag. Nennen wir es auth_app.
  2. Anwendung mit Daten. Nennen wir es App.
  3. Für jede der Anwendungen in Abschnitt 2 benötigen wir eine separate PostgreSQL-Datenbank.
  4. Anwendung zum automatischen Abrufen und Erneuern von SSL-Verschlüsselungszertifikaten (im nächsten Artikel).


Offensichtlich muss ein solcher „Zoo“ von Anwendungen voneinander isoliert und auch von außen blockiert werden. Dazu verwenden wir die Docker- Containerisierungstechnologie und den Docker Compose Container Manager . In Form eines Diagramms kann dies wie folgt dargestellt werden: Die



Bild



Entwicklung wird in der Visual Studio Code IDE von Microsoft durchgeführt, die es Ihnen dank der vielen verfügbaren Plugins ermöglicht, mit allen erforderlichen Technologien zu arbeiten. Sie müssen auch die folgenden Erweiterungen installieren:





Stellen Sie nach dem Neustart von VScode eine Verbindung zu unserem VPS her. Drücken Sie F1 und geben Sie den folgenden Befehl ein:



Remote-SSH: connect to  Host…


dann eine neue Verbindung:



+ Add New Ssh Host


dann:



ssh root@<ip- >


Öffnen Sie ein VScode-Terminalfenster (Menü / Terminal / Neues Terminal) und überprüfen Sie die Systemressourcen mit dem folgenden Befehl:



top


Wenn Sie fertig sind, erhalten Sie Zugriff auf die VPS-Konsole und das Dateisystem:











Das Top-Dienstprogramm wird häufig verwendet. Installieren Sie also die Pseudo-HTTP-Version:



Ctrl-C #   top


apt-get update #  


apt-get install htop # htop 


htop # 


Bild



Jetzt müssen Sie Docker und Docker Compose installieren:



Ctrl-C #   htop


Da sich Docker nicht im offiziellen Ubuntu-Repository befindet, werden wir ein zusätzliches Repository installieren



apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common #   


curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - #   docker 


add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" #  


apt-get install docker-ce docker-ce-cli containerd.io #


curl -L "https://github.com/docker/compose/releases/download/1.26.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose #  Docker compose 


chmod +x /usr/local/bin/docker-compose #     « »


ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose #       


 docker  --version #


docker-compose --version


Großartig, der Server ist bereit, die Bereitstellung des Dienstes zu testen.



Lassen Sie uns nun den Docker-Desktop auf unserem lokalen Entwicklungs-PC installieren. Installer für Windows 10 , MacOS-Version hier . Es wird nicht nur Docker installiert, sondern auch die Docker-Toolbox, die Docker Compose- und grafische Dienstprogramme für die Arbeit mit Containern enthält.



Öffnen wir ein neues VScode-Fenster, Menü / Datei / Ordner öffnen ... Erstellen wir einen neuen Ordner für unser Projekt, z. B. Srv, und öffnen Sie ihn. Erstellen Sie in diesem Ordner die Datei docker-compose.yaml :



Bild



Diese Datei beschreibt das Skript zum Starten der Dienstcontainer , ihre Abhängigkeiten, Variablen, Befehle, Netzwerke, Speicher usw.



Hier müssen wir anhalten und den Unterschied zwischen einem Image und einem Docker-Container klären. Ein Container ist eine Anwendung + ihre Abhängigkeiten (z. B. Pakete und Bibliotheken) + ein Betriebssystem, das Sie mit Docker als normale Anwendung ausführen können. Und ein Bild ist ein Container, der für den Start vorbereitet und in ein Archiv gepackt wird. Daher besteht unser gesamtes Backend aus einer Reihe von Containern mit einer Beschreibung des Skripts für den Start.



Der erste Container, den wir geplant haben, ist der NGINX-HTTP-Server. Und bereiten wir das notwendige Bild vor ... oder nicht? Tatsache ist, dass die Entwickler oder die Community für sehr viele Webanwendungen und deren Laufzeitumgebungen bereits die erforderlichen Images gesammelt und in die öffentliche DockerHub-Registrierung gestellt haben . Natürlich wurde ein so weit verbreitetes Bild bereits zusammengestellt und erwartet uns diesbezüglichLink .



Beachten Sie die Liste - dies sind verschiedene Versionen, sie unterscheiden sich sowohl in den Versionen von NGINX selbst als auch in zusätzlichen Tools (z. B. von PERL installiert). Für die Entwicklung können Sie das "neueste" Tag verwenden (die neueste stabile Version zum Zeitpunkt der Image-Anforderung). Für die Bereitstellung auf dem Server sollten Sie natürlich eine bestimmte Version verwenden. Im Moment ist dies das Nginx- Bild : 1.19.0 .



Im Folgenden werde ich die erforderlichen Erklärungen zum Inhalt von docker-compose.yaml in den Kommentaren in der Dateiliste selbst angeben:







Speichern Sie die Änderungen in der Datei, öffnen Sie die VScode-Konsole und führen Sie den Befehl zum Starten des Skripts aus



docker-compose up


Dieser Befehl führte nicht nur das Skript aus, sondern sendete auch die Containerkonsolenausgabe an die Hostkonsole. Wenn Sie sich nun an den lokalen Host an Port 8081 in der Adressleiste Ihres Browsers wenden, erhalten Sie die Standard-NGINX-Antwort:







Unser erster Container wird bereits ausgeführt. Normalerweise wird das Skript mit dem folgenden Befehl ausgeführt:



docker-compose up -d


Dadurch können Container im Servicemodus (ohne Konsolenausgabe) gestartet werden. Das Stoppen von Skriptcontainern erfolgt mit dem folgenden Befehl:



docker-compose down


Zum Testen von http-Anforderungen verfügt VScode über eine praktische REST-Client- Erweiterung .



Lassen Sie es uns installieren und den ersten Debug-Test unseres Dienstes schreiben. Erstellen Sie dazu eine client.http- Datei im Ordner test / http_dev / :











So können Sie Testanforderungen ausführen, indem Sie die detaillierten Informationen zu den Antworten des Servers anzeigen .



Schauen wir uns jetzt den Container an. Stoppen Sie die Skriptausführung in der Konsole:



Ctrl-C


und laufen mit einer Flagge:



docker-compose up -d


Fordern wir nun eine Liste der aktuell ausgeführten Container (Prozesse) an:



docker-compose ps






Die Liste der ausführbaren Dateien enthält nur einen Container. Öffnen wir es:



docker exec -it srv_web_1 bash


Dieser Befehl führt eine Bash-Anwendung (Linux-Befehlsshell) im Container srv_web_1 aus (exec) und verhindert, dass die Konsole geschlossen wird (-it-Flags):







Der Befehl lszeigt die Standard-Linux-Ordnerstruktur an:







Wir interessieren uns für die Datei /etc/nginx/conf.d/default.conf - In den NGINX-Einstellungen können Sie das Dienstprogramm cat zum Anzeigen verwenden



cat /etc/nginx/conf.d/default.conf






In den NGINX-Einstellungen gibt es einen Block (den sogenannten Speicherort ), in dem das Abhören von Port 80 und das Bereitstellen statischer Dateien aus dem Containerordner / usr / share / nginx / html aktiviert ist . Sie können versuchen, Änderungen an der NGINX-Konfigurationsdatei vorzunehmen und diese unter Anwendung der Änderungen neu zu starten. Wenn Sie das Skript jedoch neu starten, wird der Container aus dem Image wiederhergestellt und keine unserer Änderungen wird gespeichert. Das ist der falsche Weg.



Verlassen wir die Containerkonsole:



Ctrl-D


Wir schreiben unsere Konfigurationsdatei und platzieren unsere statischen Dateien. Beim Start werden wir sie in den NGINX-Container einbinden. Erstellen Sie eine default.conf- Datei im Ordner /conf.d unseres Projekts:











Erstellen Sie einen Stub für die statische Datei /public/index.html : Mounten Sie







nun im Startskript docker-compose.yaml unsere Ordner in das Container-Dateisystem:







Beachten Sie den Inhalt des Projektordners. /conf.d ersetzt den Inhalt des Containers in /etc/nginx/conf.d/, und der Ordner ./public wird in den Stammordner des Containerordners eingebunden.



Lassen Sie uns das Skript neu starten:



docker-compose restart


Testanforderung:







Schauen wir uns die Datei default.conf an . Bitte beachten Sie, dass wir die Protokollierung des Zugriffs auf statische Dateien access_log off deaktiviert haben . Dies ist eine gute Verkaufslösung, aber für Tests und Entwicklung sehr unpraktisch. Erstellen wir eine Test-NGINX-Konfigurationsdatei /conf.dev.d/default.conf und ein Docker-compose.dev.yaml-Skript .















Beenden wir das Skript:



docker-compose down


und führen Sie es mit Dateinamenflags aus:



docker-compose -f docker-compose.yaml -f docker-compose.dev.yaml up


Wenn Sie das Skript auf diese Weise ausführen , werden zuerst die Einstellungen aus der Datei docker-compose.yaml gelesen und anschließend passende Felder aus docker-compose.dev.yaml (Ports, Volumes) hinzugefügt oder ersetzt . Überprüfen wir die Protokollierung, indem











wir die Anforderung wiederholen: Wir müssen also nur kopieren und auf dem Server ausführen. Erstellen Sie den Ordner / opt / srv_0 / auf dem Server (wir haben das VScode-Fenster mit SSH-Verbindung zum VPS noch nicht geschlossen) und kopieren Sie den gesamten Inhalt unseres Projekts mit dem folgenden Befehl hinein:



scp scp -r ./* root@91.230.60.120:/opt/srv_0/ 






Führen Sie nun auf dem Server im Projektordner / opt / srv_0 / den folgenden Befehl aus:



docker-compose up -d


Schreiben wir jetzt einen weiteren http-Test für VPS:







Oder öffnen Sie den Link im Browser .



-> Quellcode Github



Anstelle einer Schlussfolgerung



Der erste Schritt ist also getan. Wir haben die Anwendung erfolgreich auf dem Produktionsserver bereitgestellt. Im zweiten Artikel werden wir den Server weiter konfigurieren, indem wir einen Domänennamen zuweisen und ein SSL-Verschlüsselungszertifikat installieren. Im dritten Artikel schreiben wir eine flatternde Webanwendung mit einem Countdown bis zum Start unseres Dienstes, erstellen sie und platzieren sie auf unserem Server. Im vierten Artikel werden wir einen nativen Linux-Server in der Dart-Sprache schreiben und erstellen, der die Grundlage für Autorisierungsanwendungen und Daten für unseren Dienst bildet.



Kommentare und Vorschläge sind willkommen. Sie können mit dem Autor im Telegrammkanal chatten .



All Articles