So richten Sie eine skalierbare Laravel 6-Anwendung mit verwalteten Datenbanken und Objektspeicher ein

Einführung

Bei der horizontalen Skalierung von Webanwendungen treten in der Regel als erstes Probleme bei der Speicherung von Dateien und der Datenpersistenz auf. Dies ist hauptsächlich auf die Tatsache zurückzuführen, dass es schwierig ist, die Konsistenz variabler Daten zwischen mehreren Anwendungsknoten aufrechtzuerhalten. Es müssen geeignete Strategien vorhanden sein, um sicherzustellen, dass auf einem Knoten erstellte Daten anderen Knoten in einem Cluster sofort zur Verfügung stehen.

Ein praktischer Weg zur Lösung des Konsistenzproblems ist die Verwendung von managed databases und https://www.digitalocean.com/community/tutorials/object -Storage-vs-Block-Storage-Services [Objektspeicher] -Systeme. Bei der ersten Methode wird die Datenpersistenz in eine verwaltete Datenbank ausgelagert, und bei der zweiten Methode wird ein Remotespeicherdienst bereitgestellt, über den Sie statische Dateien und variable Inhalte wie von Benutzern hochgeladene Bilder aufbewahren können. Jeder Knoten kann dann auf Anwendungsebene eine Verbindung zu diesen Diensten herstellen.

Das folgende Diagramm zeigt, wie ein solches Setup für die horizontale Skalierbarkeit im Kontext von PHP-Anwendungen verwendet werden kann:

image: https: //assets.digitalocean.com/articles/laravel_at_scale/scaling_laravel_final.png [Laravel at scale diagram]

In diesem Handbuch aktualisieren wir eine vorhandene Laravel 6-Anwendung, um sie für die horizontale Skalierbarkeit vorzubereiten, indem wir sie mit einer verwalteten MySQL-Datenbank verbinden und einen S3-kompatiblen Objektspeicher einrichten, um vom Benutzer generierte Dateien zu speichern. Am Ende wird eine Reiselistenanwendung auf einem Nginx + PHP-FPM-Webserver ausgeführt:

Voraussetzungen

Um dieses Tutorial zu beginnen, benötigen Sie zunächst die folgenden Voraussetzungen:

  • Zugriff auf einen Ubuntu 18.04-Server als Nicht-Root-Benutzer mit Sudo-Berechtigungen und einer auf Ihrem Server installierten aktiven Firewall. Informationen zum Einrichten finden Sie unter Initial Server Setup Guide for Ubuntu 18.04.

  • Nginx und PHP-FPM werden auf Ihrem Server installiert und konfiguriert, wie in den Schritten * 1 * und * 3 * von https://www.digitalocean.com/community/tutorials/how-to-install-linux-nginx-mysql- erläutert. php-lemp-stack-ubuntu-18-04 [LEMP unter Ubuntu 18.04 installieren]. Sie sollten den Schritt überspringen, in dem MySQL installiert ist.

  • Composer auf Ihrem Server installiert, wie in den Schritten * 1 * und * 2 * von https://www.digitalocean.com/community/tutorials/how-to-install-and- use-composer-on-ubuntu-18-04 [Installieren und Verwenden von Composer unter Ubuntu 18.04].

  • Administratoranmeldeinformationen für eine verwaltete MySQL 8-Datenbank. Für dieses Handbuch verwenden wir einen DigitalOcean Managed MySQL -Cluster, aber die Anweisungen hier sollten ähnlich funktionieren für andere verwaltete Datenbankdienste.

  • Eine Reihe von API-Schlüsseln mit Lese- und Schreibberechtigungen für einen S3-kompatiblen Objektspeicherdienst. In diesem Handbuch wird DigitalOcean Spaces verwendet, es steht Ihnen jedoch frei, einen Anbieter Ihrer Wahl zu verwenden.

  • Das Tool + s3cmd + wurde installiert und konfiguriert, um eine Verbindung zu Ihrem Objektspeicherlaufwerk herzustellen. Anweisungen zum Einrichten für DigitalOcean Spaces finden Sie in unserer product documentation.

Schritt 1 - Installieren des MySQL 8-Clients

Die Standard-Repositorys von Ubuntu apt werden mit dem MySQL 5-Client geliefert, der nicht mit dem in diesem Handbuch verwendeten MySQL 8-Server kompatibel ist. Um den kompatiblen MySQL-Client zu installieren, müssen Sie das von Oracle bereitgestellte MySQL APT Repository verwenden.

Navigieren Sie zunächst in Ihrem Webbrowser zur Seite MySQL APT Repository. Suchen Sie die Schaltfläche Download in der rechten unteren Ecke und klicken Sie sich zur nächsten Seite durch. Auf dieser Seite werden Sie aufgefordert, sich anzumelden oder sich für ein Oracle-Webkonto anzumelden. Sie können das überspringen und stattdessen nach dem Link suchen, der "Nein, danke" sagt, starten Sie einfach meinen Download. Kopieren Sie die Linkadresse und kehren Sie zu Ihrem Terminalfenster zurück.

Dieser Link sollte auf ein "+ .deb " - Paket verweisen, mit dem das MySQL APT-Repository auf Ihrem Server eingerichtet wird. Nach der Installation können Sie mit " apt " die neuesten Versionen von MySQL installieren. Wir verwenden " curl +", um diese Datei an einen temporären Speicherort herunterzuladen.

Gehen Sie zu Ihrem Server-Ordner "+ tmp":

cd /tmp

Laden Sie nun das Paket mit + curl + und der von der MySQL APT Repository-Seite kopierten URL herunter:

curl -OL

Nachdem der Download abgeschlossen ist, können Sie das Paket mit + dpkg + installieren:

sudo dpkg -i

Es wird ein Bildschirm angezeigt, in dem Sie auswählen können, welche MySQL-Version Sie als Standard auswählen möchten und welche MySQL-Komponenten Sie interessieren:

Sie müssen hier nichts ändern, da die von uns benötigten Repositorys mit den Standardoptionen installiert werden. Wählen Sie „Ok“ und die Konfiguration wird beendet.

Als nächstes müssen Sie Ihren '+ apt'-Cache aktualisieren mit:

sudo apt update

Jetzt können wir endlich den MySQL 8 Client installieren mit:

sudo apt install mysql-client

Überprüfen Sie nach Abschluss dieses Befehls die Versionsnummer der Software, um sicherzustellen, dass Sie über die neueste Version verfügen:

mysql --version

Die Ausgabe sieht folgendermaßen aus:

Outputmysql  Ver  for Linux on x86_64 (MySQL Community Server - GPL)

Im nächsten Schritt stellen wir mit dem MySQL-Client eine Verbindung zu Ihrem verwalteten MySQL-Server her und bereiten die Datenbank für die Anwendung vor.

Schritt 2 - Erstellen eines neuen MySQL-Benutzers und einer neuen Datenbank

Zum Zeitpunkt des Schreibens unterstützt die native MySQL-PHP-Bibliothek "+ mysqlnd " (https://www.php.net/manual/en/ref.pdo-mysql.php[) nicht " caching_sha2_authentication " (Standard) Authentifizierungsmethode für MySQL 8. Wir müssen einen neuen Benutzer mit der Authentifizierungsmethode " mysql_native_password +" erstellen, um unsere Laravel-Anwendung mit dem MySQL 8-Server verbinden zu können. Wir erstellen auch eine dedizierte Datenbank für unsere Demo-Anwendung.

Melden Sie sich zunächst mit einem Administratorkonto bei Ihrem Server an. Ersetzen Sie die hervorgehobenen Werte durch Ihren eigenen MySQL-Benutzer, Host und Port:

mysql -u  -p -h  -P

Wenn Sie dazu aufgefordert werden, geben Sie das Kennwort des Administratorbenutzers ein. Nach dem Anmelden haben Sie Zugriff auf die Befehlszeilenschnittstelle des MySQL 8-Servers.

Zunächst erstellen wir eine neue Datenbank für die Anwendung. Führen Sie den folgenden Befehl aus, um eine neue Datenbank mit dem Namen "++" zu erstellen:

CREATE DATABASE ;

Als Nächstes erstellen wir einen neuen Benutzer und legen ein Kennwort fest, wobei wir "+ mysql_native_password +" als Standardauthentifizierungsmethode für diesen Benutzer verwenden. Es wird empfohlen, die hervorgehobenen Werte durch eigene Werte zu ersetzen und ein sicheres Passwort zu verwenden:

CREATE USER ''@'%' IDENTIFIED WITH mysql_native_password BY '';

Jetzt müssen wir diesem Benutzer die Berechtigung für unsere Anwendungsdatenbank erteilen:

GRANT ALL ON .* TO ''@'%';

Sie können die MySQL-Eingabeaufforderung jetzt mit folgendem Befehl beenden:

exit;

Sie haben jetzt eine dedizierte Datenbank und einen kompatiblen Benutzer, um eine Verbindung mit Ihrer Laravel-Anwendung herzustellen. Im nächsten Schritt erhalten wir den Anwendungscode und richten die Konfigurationsdetails ein, damit Ihre App eine Verbindung zu Ihrer verwalteten MySQL-Datenbank herstellen kann.

Schritt 3 - Einrichten der Demo-Anwendung

Zunächst rufen wir die Demo-Laravel-Anwendung aus dem Github repository ab. Sie können den Inhalt der Anwendung überprüfen, bevor Sie die nächsten Befehle ausführen.

Die Demo-Anwendung ist eine Travel Bucket List-App, die ursprünglich in unserem Handbuch unter https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-laravel-with-lemp-on-ubuntu entwickelt wurde -18-04 [Installieren und Konfigurieren von Laravel mit LEMP unter Ubuntu 18.04]. Die aktualisierte App enthält jetzt visuelle Verbesserungen, einschließlich Reisefotos, die von einem Besucher hochgeladen werden können, und eine Weltkarte. Außerdem werden ein Datenbankmigrationsskript und Datenbank-Seeds eingeführt, um die Anwendungstabellen zu erstellen und sie mit Beispieldaten zu füllen, die mit den Befehlen "+ artisan +" verwendet werden.

Um den Anwendungscode zu erhalten, der mit diesem Tutorial kompatibel ist, laden wir die https://github.com/do-community/travellist-laravel-demo/releases/tag/1.1 [+ 1.1 + release] von der herunter Projektarchiv auf Github. Wir speichern die heruntergeladene Zip-Datei unter dem Namen "+ travellist.zip +" in unserem Home-Verzeichnis:

cd ~
curl -L https://github.com/do-community/travellist-laravel-demo/archive/1.1.zip -o travellist.zip

Entpacken Sie nun den Inhalt der Anwendung und benennen Sie das Verzeichnis um mit:

unzip travellist.zip
mv travellist-laravel-demo-1.1 travellist

Navigieren Sie zum Verzeichnis "+ travellist +":

cd travellist

Bevor wir fortfahren, müssen wir einige PHP-Module installieren, die für das Laravel-Framework erforderlich sind, nämlich: "+ php-xml ", " php-mbstring ", " php-xml " und " php-bcmath +" `. Führen Sie zum Installieren dieser Pakete Folgendes aus:

sudo apt install unzip php-xml php-mbstring php-xml php-bcmath

Führen Sie zum Installieren der Anwendungsabhängigkeiten Folgendes aus:

composer install

Sie werden eine Ausgabe ähnlich der folgenden sehen:

OutputLoading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 80 installs, 0 updates, 0 removals
 - Installing doctrine/inflector (v1.3.0): Downloading (100%)
 - Installing doctrine/lexer (1.1.0): Downloading (100%)
 - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%)
 - Installing erusev/parsedown (1.7.3): Downloading (100%)

...

Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: beyondcode/laravel-dump-server
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.

Die Anwendungsabhängigkeiten sind jetzt installiert. Als Nächstes konfigurieren wir die Anwendung für die Verbindung mit der verwalteten MySQL-Datenbank.

Erstellen der Konfigurationsdatei "+ .env +" und Festlegen des Anwendungsschlüssels

Wir erstellen jetzt eine "+ .env +" - Datei mit Variablen, die zum Konfigurieren der Laravel-Anwendung pro Umgebung verwendet werden. Die Anwendung enthält eine Beispieldatei, die wir kopieren und anschließend an die Umgebungseinstellungen anpassen können.

Kopieren Sie die Datei "+ .env.example" in eine neue Datei mit dem Namen "+ .env":

cp .env.example .env

Jetzt müssen wir den Anwendungsschlüssel einstellen. Dieser Schlüssel wird zum Verschlüsseln von Sitzungsdaten verwendet und sollte auf eine eindeutige Zeichenfolge mit 32 Zeichen festgelegt werden. Wir können diesen Schlüssel automatisch mit dem + artisan + Tool generieren:

php artisan key:generate

Bearbeiten Sie die Umgebungskonfigurationsdatei, um die Datenbankdetails einzurichten. Öffnen Sie die Datei + .env + mit dem Befehlszeileneditor Ihrer Wahl. Hier verwenden wir + nano +:

nano .env

Suchen Sie nach dem Abschnitt mit den Datenbankanmeldeinformationen. Die folgenden Variablen benötigen Ihre Aufmerksamkeit:

+ DB_HOST +: Ihr verwalteter MySQL Server Host. + + DB_PORT +: Ihr verwalteter MySQL-Server-Port. + + DB_DATABASE +: Der Name der Anwendungsdatenbank, die wir im Link erstellt haben: # step-2-% E2% 80% 94-erstelle-einen-neuen-mysql-Benutzer-und-Datenbank [Schritt 2]. + + DB_USERNAME +: Der Datenbankbenutzer, den wir im Link erstellt haben: # step-2-% E2% 80% 94-Erstellen-eines-neuen-mysql-Benutzers-und-einer-Datenbank [Schritt 2]. + + DB_PASSWORD +: Das Passwort für den Datenbankbenutzer, das wir unter dem folgenden Link definiert haben: # step-2-% E2% 80% 94-create-a-new-mysql-user-and-database [Schritt 2].

Aktualisieren Sie die hervorgehobenen Werte mit Ihren eigenen verwalteten MySQL-Informationen und -Anmeldeinformationen:

...
DB_CONNECTION=mysql
DB_HOST=
DB_PORT=
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=
...

Speichern und schließen Sie die Datei, indem Sie "+ STRG + X ", dann " Y " und " EINGABE +" eingeben, wenn Sie mit der Bearbeitung fertig sind.

Nachdem die Anwendung für die Verbindung mit der MySQL-Datenbank konfiguriert wurde, können wir Laravels Befehlszeilentool "+ artisan +" verwenden, um die Datenbanktabellen zu erstellen und sie mit Beispieldaten zu füllen.

Migrieren und Auffüllen der Datenbank

Wir werden jetzt Laravel Migrations und database seeds verwenden, um die Anwendungstabellen einzurichten. Auf diese Weise können wir feststellen, ob unsere Datenbankkonfiguration wie erwartet funktioniert.

Führen Sie Folgendes aus, um das Migrationsskript auszuführen, mit dem die von der Anwendung verwendeten Tabellen erstellt werden:

php artisan migrate

Sie werden eine Ausgabe ähnlich der folgenden sehen:

OutputMigration table created successfully.
Migrating: 2019_09_19_123737_create_places_table
Migrated:  2019_09_19_123737_create_places_table (0.26 seconds)
Migrating: 2019_10_14_124700_create_photos_table
Migrated:  2019_10_14_124700_create_photos_table (0.42 seconds)

Führen Sie Folgendes aus, um die Datenbank mit Beispieldaten zu füllen:

php artisan db:seed

Sie sehen die Ausgabe wie folgt:

OutputSeeding: PlacesTableSeeder
Seeded:  PlacesTableSeeder (0.86 seconds)
Database seeding completed successfully.

Die Anwendungstabellen werden nun erstellt und mit Beispieldaten gefüllt.

Einrichten der Speicherverbindung

Um die Einrichtung der Anwendung abzuschließen, müssen Sie außerdem einen symbolischen Link zum öffentlichen Speicherordner erstellen, in dem die in der Anwendung verwendeten Reisefotos gespeichert werden. Sie können das mit dem + artisan + Werkzeug machen:

php artisan storage:link
OutputThe [public/storage] directory has been linked.

Dadurch wird ein symbolischer Link im Verzeichnis "+ public" erstellt, der auf "+ storage / app / public" verweist, in dem die Reisefotos gespeichert werden. Um zu überprüfen, ob der Link erstellt wurde und wohin er verweist, können Sie Folgendes ausführen:

ls -la public/

Die Ausgabe sieht folgendermaßen aus:

Outputtotal 36
drwxrwxr-x  5 sammy sammy 4096 Oct 25 14:59 .
drwxrwxr-x 12 sammy sammy 4096 Oct 25 14:58 ..
-rw-rw-r--  1 sammy sammy  593 Oct 25 06:29 .htaccess
drwxrwxr-x  2 sammy sammy 4096 Oct 25 06:29 css
-rw-rw-r--  1 sammy sammy    0 Oct 25 06:29 favicon.ico
drwxrwxr-x  2 sammy sammy 4096 Oct 25 06:29 img
-rw-rw-r--  1 sammy sammy 1823 Oct 25 06:29 index.php
drwxrwxr-x  2 sammy sammy 4096 Oct 25 06:29 js
-rw-rw-r--  1 sammy sammy   24 Oct 25 06:29 robots.txt

-rw-rw-r--  1 sammy sammy 1194 Oct 25 06:29 web.config

Ausführen des Testservers (optional)

Mit dem Befehl "+ artisan serve +" können Sie schnell überprüfen, ob in der Anwendung alles korrekt eingerichtet ist, bevor Sie einen voll ausgestatteten Webserver wie Nginx konfigurieren müssen, um die Anwendung langfristig bereitzustellen.

Wir werden den Port "+ 8000 +" verwenden, um die Anwendung vorübergehend zum Testen bereitzustellen. Wenn Sie die UFW-Firewall auf Ihrem Server aktiviert haben, sollten Sie zunächst den Zugriff auf diesen Port über Folgendes zulassen:

sudo ufw allow 8000

Um den eingebauten PHP-Server auszuführen, den Laravel mit dem Tool + artisan + zur Verfügung stellt, führen Sie Folgendes aus:

php artisan serve --host=0.0.0.0 --port=8000

Dieser Befehl blockiert Ihr Terminal, bis er mit einem "+ CTRL + C " unterbrochen wird. Es verwendet den eingebauten PHP-Webserver, um die Anwendung zu Testzwecken auf allen Netzwerkschnittstellen unter Verwendung des Ports " 8000 +" bereitzustellen.

Rufen Sie nun Ihren Browser auf und greifen Sie über den Domainnamen oder die IP-Adresse des Servers an Port "+ 8000 +" auf die Anwendung zu:

http://:8000

Sie sehen die folgende Seite:

Wenn Sie diese Seite sehen, bedeutet dies, dass die Anwendung erfolgreich Daten zu Standorten und Fotos aus der konfigurierten verwalteten Datenbank abruft. Die Bilddateien werden immer noch auf der lokalen Festplatte gespeichert. Dies wird jedoch in einem der folgenden Schritte dieses Handbuchs geändert.

Wenn Sie mit dem Testen der Anwendung fertig sind, können Sie den Befehl + serve + stoppen, indem Sie + CTRL + C + drücken.

Vergessen Sie nicht, den Port "+ 8000 +" erneut zu schließen, wenn Sie UFW auf Ihrem Server ausführen:

sudo ufw deny 8000

Schritt 4 - Konfigurieren von Nginx für die Bereitstellung der Anwendung

Obwohl der integrierte PHP-Webserver für Entwicklungs- und Testzwecke sehr nützlich ist, ist er nicht als langfristige Lösung für PHP-Anwendungen gedacht. Es wird empfohlen, einen voll ausgestatteten Webserver wie Nginx zu verwenden.

Zu Beginn verschieben wir den Anwendungsordner nach "+ / var / www ". Dies ist der übliche Speicherort für Webanwendungen, die unter Nginx ausgeführt werden. Verwenden Sie zuerst den Befehl " mv ", um den Anwendungsordner mit seinem gesamten Inhalt nach " / var / www / travellist +" zu verschieben:

sudo mv ~/ /var/www/

Jetzt müssen wir dem Webserver-Benutzer Schreibzugriff auf die Ordner "+ storage" und "+ bootstrap / cache" gewähren, in denen Laravel anwendungsgenerierte Dateien speichert. Wir werden diese Berechtigungen mit "+ setfacl +" festlegen, einem Befehlszeilenprogramm, das robustere und differenziertere Berechtigungseinstellungen in Dateien und Ordnern ermöglicht.

Führen Sie Folgendes aus, um dem Webserver-Benutzer Lese-, Schreib- und Ausführungsberechtigungen (rwx) für die erforderlichen Verzeichnisse zu erteilen:

sudo setfacl -R -m g:www-data:rwx /var/www/travellist/storage
sudo setfacl -R -m g:www-data:rwx /var/www/travellist/bootstrap/cache

Die Anwendungsdateien sind jetzt in Ordnung, aber wir müssen Nginx noch konfigurieren, um den Inhalt bereitzustellen. Dazu erstellen wir eine neue Konfigurationsdatei für virtuelle Hosts unter "+ / etc / nginx / sites-available +":

sudo nano /etc/nginx/sites-available/

Die folgende Konfigurationsdatei enthält die Einstellungen für recommended für Laravel-Anwendungen auf Nginx:

/ etc / nginx / sites-available / travellist

server {
   listen 80;
   server_name ;
   root /var/www//public;

   add_header X-Frame-Options "SAMEORIGIN";
   add_header X-XSS-Protection "1; mode=block";
   add_header X-Content-Type-Options "nosniff";

   index index.html index.htm index.php;

   charset utf-8;

   location / {
       try_files $uri $uri/ /index.php?$query_string;
   }

   location = /favicon.ico { access_log off; log_not_found off; }
   location = /robots.txt  { access_log off; log_not_found off; }

   error_page 404 /index.php;

   location ~ \.php$ {
       fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
       fastcgi_index index.php;
       fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
       include fastcgi_params;
   }

   location ~ /\.(?!well-known).* {
       deny all;
   }
}

Kopieren Sie diesen Inhalt in Ihre Datei "+ / etc / nginx / sites-available / +" und passen Sie die hervorgehobenen Werte an Ihre eigene Konfiguration an. Speichern und schließen Sie die Datei, wenn Sie mit der Bearbeitung fertig sind.

Um die neue Konfigurationsdatei für virtuelle Hosts zu aktivieren, erstellen Sie einen symbolischen Link zu "+ travellist " in " sites-enabled +":

sudo ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/

Um zu bestätigen, dass die Konfiguration keine Syntaxfehler enthält, können Sie Folgendes verwenden:

sudo nginx -t

Sie sollten die Ausgabe so sehen:

Outputnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Um die Änderungen zu übernehmen, laden Sie Nginx neu mit:

sudo systemctl reload nginx

Wenn Sie Ihren Browser jetzt neu laden, werden die Anwendungsbilder beschädigt. Dies liegt daran, dass wir das Anwendungsverzeichnis an einen neuen Speicherort innerhalb des Servers verschoben haben und daher die symbolische Verknüpfung zum Anwendungsspeicherordner neu erstellen müssen.

Entfernen Sie den alten Link mit:

cd /var/www/
rm -f public/storage

Führen Sie nun noch einmal den Befehl + artisan + aus, um den Speicherlink zu generieren:

php artisan storage:link

Rufen Sie nun Ihren Browser auf und greifen Sie auf die Anwendung zu, indem Sie den Domänennamen oder die IP-Adresse des Servers verwenden, wie in der Direktive "+ Servername +" in Ihrer Konfigurationsdatei definiert:

http://

Im nächsten Schritt integrieren wir einen Objektspeicherdienst in die Anwendung. Dadurch wird der derzeitige lokale Festplattenspeicher für die Reisefotos ersetzt.

Schritt 5 - Integrieren eines S3-kompatiblen Objektspeichers in die Anwendung

Wir richten die Anwendung jetzt so ein, dass sie einen S3-kompatiblen Objektspeicherdienst zum Speichern der auf der Indexseite gezeigten Reisefotos verwendet. Da in der Anwendung bereits einige Beispielfotos auf der lokalen Festplatte gespeichert sind, verwenden wir auch das Tool https://s3tools.org/s3cmd [+ s3cmd +], um die vorhandenen lokalen Bilddateien in den Remote-Objektspeicher hochzuladen.

Einrichten des S3-Treibers für Laravel

Laravel verwendet "+ league / flysystem ", eine Dateisystem-Abstraktionsbibliothek, mit der eine Laravel-Anwendung mehrere Speicherlösungen einschließlich lokaler Festplatten- und Cloud-Dienste verwenden und kombinieren kann. Ein zusätzliches Paket ist erforderlich, um den ` s3 ` - Treiber zu verwenden. Wir können dieses Paket mit dem Befehl ` composer require +` installieren.

Greifen Sie auf das Anwendungsverzeichnis zu:

cd /var/www/
composer require league/flysystem-aws-s3-v3

Sie werden eine Ausgabe ähnlich der folgenden sehen:

OutputUsing version ^1.0 for league/flysystem-aws-s3-v3
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 8 installs, 0 updates, 0 removals
 - Installing mtdowling/jmespath.php (2.4.0): Loading from cache
 - Installing ralouphie/getallheaders (3.0.3): Loading from cache
 - Installing psr/http-message (1.0.1): Loading from cache
 - Installing guzzlehttp/psr7 (1.6.1): Loading from cache
 - Installing guzzlehttp/promises (v1.3.1): Loading from cache
 - Installing guzzlehttp/guzzle (6.4.1): Downloading (100%)
 - Installing aws/aws-sdk-php (3.112.28): Downloading (100%)
 - Installing league/flysystem-aws-s3-v3 (1.0.23): Loading from cache
...

Nachdem die erforderlichen Pakete installiert wurden, können wir die Anwendung aktualisieren, um eine Verbindung zum Objektspeicher herzustellen. Zuerst öffnen wir die Datei "+ .env +" erneut, um Konfigurationsdetails wie Schlüssel, Bucket-Name und Region für Ihren Objektspeicherdienst einzurichten.

Öffnen Sie die Datei + .env +:

nano .env

Schließen Sie die folgenden Umgebungsvariablen ein und ersetzen Sie die hervorgehobenen Werte durch die Konfigurationsdetails Ihres Objektspeichers:

/var/www/travellist/.env

DO_SPACES_KEY=
DO_SPACES_SECRET=
DO_SPACES_ENDPOINT=
DO_SPACES_REGION=
DO_SPACES_BUCKET=

Speichern und schließen Sie die Datei, wenn Sie fertig sind. Öffnen Sie nun die Datei + config / filesystems.php +:

nano config/filesystems.php

In dieser Datei erstellen wir einen neuen disk-Eintrag im Array + disks +. Wir benennen diese Festplatte mit "+ Leerzeichen " und verwenden die Umgebungsvariablen, die wir in der Datei " .env " festgelegt haben, um die neue Festplatte zu konfigurieren. Fügen Sie den folgenden Eintrag in das Array ` disks +` ein:

config / filesystems.php

'spaces' => [
  'driver' => 's3',
  'key' => env('DO_SPACES_KEY'),
  'secret' => env('DO_SPACES_SECRET'),
  'endpoint' => env('DO_SPACES_ENDPOINT'),
  'region' => env('DO_SPACES_REGION'),
  'bucket' => env('DO_SPACES_BUCKET'),
],

Suchen Sie in derselben Datei den Eintrag "+ cloud " und ändern Sie ihn, um die neue " spaces +" - Festplatte als Standardfestplatte für das Cloud-Dateisystem festzulegen:

config / filesystems.php

'cloud' => env('FILESYSTEM_CLOUD', ''),
Speichern und schließen Sie die Datei, wenn Sie mit der Bearbeitung fertig sind. Auf Ihren Controllern können Sie jetzt die Methode "+ Storage

cloud () " als Verknüpfung verwenden, um auf die Standardfestplatte " cloud +" zuzugreifen. Auf diese Weise bleibt die Anwendung flexibel, um mehrere Speicherlösungen zu verwenden, und Sie können je nach Umgebung zwischen Anbietern wechseln.

Die Anwendung ist jetzt für die Verwendung des Objektspeichers konfiguriert. Der Code, mit dem neue Fotos in die Anwendung hochgeladen werden, muss jedoch aktualisiert werden.

Untersuchen wir zunächst die aktuelle Route "+ uploadPhoto " in der Klasse " PhotoController +". Öffnen Sie die Datei mit Ihrem Texteditor:

nano app/Http/Controllers/PhotoController.php

app / Http / Controllers / PhotoController.php

…

public function uploadPhoto(Request $request)
{
  $photo = new Photo();
  $place = Place::find($request->input('place'));

  if (!$place) {
      //add new place
      $place = new Place();
      $place->name = $request->input('place_name');
      $place->lat = $request->input('place_lat');
      $place->lng = $request->input('place_lng');
  }

  $place->visited = 1;
  $place->save();

  $photo->place()->associate($place);

  $photo->save();

  return redirect()->route('Main');
}

Diese Methode akzeptiert eine "+ POST" -Anforderung und erstellt einen neuen Fotoeintrag in der Fototabelle. Zunächst wird überprüft, ob im Formular zum Hochladen von Fotos ein vorhandener Ort ausgewählt wurde. Ist dies nicht der Fall, wird anhand der bereitgestellten Informationen ein neuer Ort erstellt. Der Ort wird dann auf "+ besucht " gesetzt und in der Datenbank gespeichert. Anschließend wird eine Assoziation erstellt, sodass das neue Foto mit dem angegebenen Ort verknüpft wird. Die Image-Datei wird dann im Root-Ordner der ` public +` -Diskette gespeichert. Schließlich wird das Foto in der Datenbank gespeichert. Der Benutzer wird dann zur Hauptroute weitergeleitet, der Indexseite der Anwendung.

Die hervorgehobene Zeile in diesem Code interessiert uns. In dieser Zeile wird die Bilddatei mit der Methode "+ store " auf der Festplatte gespeichert. Die Methode " store" wird verwendet, um Dateien auf einer der in der Konfigurationsdatei "+ filesystem.php" definierten Festplatten zu speichern. In diesem Fall wird der Standarddatenträger zum Speichern hochgeladener Bilder verwendet.

Wir werden dieses Verhalten so ändern, dass das Image im Objektspeicher statt auf der lokalen Festplatte gespeichert wird. Dazu müssen wir im Methodenaufruf "+ store " die " public" -Diskette durch die "+ space" -Diskette ersetzen. Wir müssen auch sicherstellen, dass die Sichtbarkeit der hochgeladenen Datei auf public anstelle von private eingestellt ist.

Der folgende Code enthält die vollständige Klasse "+ PhotoController ", einschließlich der aktualisierten Methode " uploadPhoto +":

app / Http / Controllers / PhotoController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Photo;
use App\Place;


class PhotoController extends Controller
{
  public function uploadForm()
  {
      $places = Place::all();

      return view('upload_photo', [
          'places' => $places
      ]);
  }

  public function uploadPhoto(Request $request)
  {
      $photo = new Photo();
      $place = Place::find($request->input('place'));

      if (!$place) {
          //add new place
          $place = new Place();
          $place->name = $request->input('place_name');
          $place->lat = $request->input('place_lat');
          $place->lng = $request->input('place_lng');
      }

      $place->visited = 1;
      $place->save();

      $photo->place()->associate($place);


      $photo->save();

      return redirect()->route('Main');
  }
}

Kopieren Sie den aktualisierten Code in Ihren eigenen "+ PhotoController +", damit er die hervorgehobenen Änderungen widerspiegelt. Speichern und schließen Sie die Datei, wenn Sie mit der Bearbeitung fertig sind.

Die Hauptansicht der Anwendung muss noch so geändert werden, dass sie die URL der Objektspeicherdatei verwendet, um das Bild zu rendern. Öffnen Sie die Vorlage "+ travel_list.blade.php +":

nano resources/views/travel_list.blade.php

Suchen Sie nun den Abschnitt "+ footer +" auf der Seite, der derzeit so aussieht:

resources / views / travel_list.blade.php

@section('footer')
  <h2>Travel Photos <small>[ <a href="{{ route('Upload.form') }}">Upload Photo</a> ]</small></h2>
  @foreach ($photos as $photo)
      <div class="photo">
         <img src="" />
          <p>{{ $photo->place->name }}</p>
      </div>
  @endforeach

@endsection

Ersetzen Sie das aktuelle Image-Attribut "+ src", um die Datei-URL vom Speicherplatz "+" als Speicherfestplatte zu verwenden:

<img src="" />

Wenn Sie jetzt zu Ihrem Browser gehen und die Anwendungsseite neu laden, werden nur fehlerhafte Bilder angezeigt. Dies liegt daran, dass sich die Bilddateien für diese Reisefotos immer noch nur auf der lokalen Festplatte befinden. Wir müssen die vorhandenen Bilddateien in den Objektspeicher hochladen, damit die bereits in der Datenbank gespeicherten Fotos erfolgreich auf der Anwendungsseite angezeigt werden können.

Lokale Bilder mit + s3cmd + synchronisieren

Mit dem Tool + s3cmd + können lokale Dateien mit einem S3-kompatiblen Objektspeicherdienst synchronisiert werden. Wir führen den Befehl "+ sync " aus, um alle Dateien in " storage / app / public / photos +" zum Objektspeicherdienst hochzuladen.

Greifen Sie auf das App-Speicherverzeichnis "+ public +" zu:

cd /var/www/travellist/storage/app/public

Um einen Blick auf die bereits auf Ihrer Remote-Festplatte gespeicherten Dateien zu werfen, können Sie den Befehl + s3cmd ls + verwenden:

s3cmd ls s3://

Führen Sie nun den Befehl + sync + aus, um vorhandene Dateien im öffentlichen Speicherordner in den Objektspeicher hochzuladen:

s3cmd sync ./ s3:// --acl-public --exclude=.gitignore

Dadurch wird der aktuelle Ordner (+ storage / app / public) mit dem Stammverzeichnis des Remote-Objektspeichers synchronisiert. Sie erhalten eine Ausgabe ähnlich der folgenden:

Outputupload: './bermudas.jpg' -> 's3://sammy-travellist/bermudas.jpg'  [1 of 3]
2538230 of 2538230   100% in    7s   329.12 kB/s  done
upload: './grindavik.jpg' -> 's3://sammy-travellist/grindavik.jpg'  [2 of 3]
1295260 of 1295260   100% in    5s   230.45 kB/s  done
upload: './japan.jpg' -> 's3://sammy-travellist/japan.jpg'  [3 of 3]
8940470 of 8940470   100% in   24s   363.61 kB/s  done
Done. Uploaded 12773960 bytes in 37.1 seconds, 336.68 kB/s.

Wenn Sie nun + s3cmd ls + erneut ausführen, werden Sie feststellen, dass dem Stammordner Ihres Objektspeicher-Buckets drei neue Dateien hinzugefügt wurden:

s3cmd ls s3://
Output2019-10-25 11:49   2538230   s3://sammy-travellist/bermudas.jpg
2019-10-25 11:49   1295260   s3://sammy-travellist/grindavik.jpg
2019-10-25 11:49   8940470   s3://sammy-travellist/japan.jpg

Rufen Sie Ihren Browser auf und laden Sie die Anwendungsseite neu. Alle Bilder sollten jetzt sichtbar sein. Wenn Sie sie mit den Debug-Tools Ihres Browsers überprüfen, werden Sie feststellen, dass sie alle URLs aus Ihrem Objektspeicher verwenden.

Testen der Integration

Die Demo-Anwendung ist jetzt voll funktionsfähig. Sie speichert Dateien in einem Remote-Objektspeicherdienst und speichert Daten in einer verwalteten MySQL-Datenbank. Wir können jetzt ein paar Fotos hochladen, um unser Setup zu testen.

Greifen Sie über Ihren Browser auf die Anwendungsroute "+ / upload +" zu:

http:///upload

Sie sehen folgendes Formular:

image: https: //assets.digitalocean.com/articles/laravel_at_scale/upload_form_v1.png [Formular zum Hochladen von Reisefotos]

Sie können jetzt einige Fotos hochladen, um die Objektspeicherintegration zu testen. Nachdem Sie ein Bild von Ihrem Computer ausgewählt haben, können Sie einen vorhandenen Ort aus dem Dropdown-Menü auswählen oder einen neuen Ort hinzufügen, indem Sie dessen Namen und geographic coordinates eingeben, damit es geladen werden kann in der Applikationskarte.

Schritt 6 - Skalieren einer mit DigitalOcean verwalteten MySQL-Datenbank mit schreibgeschützten Knoten (optional)

Da schreibgeschützte Vorgänge in der Regel häufiger sind als Schreibvorgänge auf Datenbankservern, ist es üblich, einen Datenbankcluster durch Einrichten mehrerer schreibgeschützter Knoten zu skalieren. Dies verteilt die Last, die durch "+ SELECT +" - Operationen erzeugt wird.

Um dieses Setup zu demonstrieren, fügen wir unserem DigitalOcean Managed MySQL-Cluster zunächst zwei schreibgeschützte Knoten hinzu. Anschließend konfigurieren wir die Laravel-Anwendung für die Verwendung dieser Knoten.

Greifen Sie auf https://cloud.digitalocean.com [DigitalOcean Cloud Panel] zu und befolgen Sie diese Anweisungen:

  1. Gehen Sie zu Datenbanken und wählen Sie Ihren MySQL-Cluster aus.

  2. Klicken Sie auf "+ Aktionen " und wählen Sie " Schreibgeschützten Knoten hinzufügen +" aus dem Dropdown-Menü.

  3. Konfigurieren Sie die Knotenoptionen und klicken Sie auf die Schaltfläche "Erstellen". Beachten Sie, dass es einige Minuten dauern kann, bis der neue Knoten bereit ist.

  4. Wiederholen Sie die Schritte 1 bis 4 ein weiteres Mal, damit Sie 2 schreibgeschützte Knoten haben.

  5. Notieren Sie sich die Hosts der beiden Knoten, da wir sie für unsere Laravel-Konfiguration benötigen.

Sobald Sie Ihre schreibgeschützten Knoten bereit haben, kehren Sie zu Ihrem Terminal zurück.

Wir werden unsere Laravel-Anwendung jetzt so konfigurieren, dass sie mit mehreren Datenbankknoten funktioniert. Wenn wir fertig sind, werden Abfragen wie "+ EINFÜGEN" und "+ AKTUALISIEREN" an Ihren primären Clusterknoten weitergeleitet, während alle "+ AUSWÄHLEN +" - Abfragen an Ihre schreibgeschützten Knoten umgeleitet werden.

Wechseln Sie zunächst in das Anwendungsverzeichnis auf dem Server und öffnen Sie die Datei "+ .env +" mit dem Texteditor Ihrer Wahl:

cd /var/www/travellist
nano .env

Suchen Sie die MySQL-Datenbankkonfiguration und kommentieren Sie die Zeile + DB_HOST + aus:

/var/www/travellist/.env

DB_CONNECTION=mysql

DB_PORT=MANAGED_MYSQL_PORT
DB_DATABASE=MANAGED_MYSQL_DB
DB_USERNAME=MANAGED_MYSQL_USER
DB_PASSWORD=MANAGED_MYSQL_PASSWORD

Speichern und schließen Sie die Datei, wenn Sie fertig sind. Öffne nun die + config / database.php + in deinem Texteditor:

nano config/database.php

Suchen Sie im Array + connections in nach dem Eintrag` + mysql`. Sie sollten * drei * neue Elemente in dieses Konfigurationsarray aufnehmen: "+ read", "+ write" und "+ sticky". Die Einträge "+ read " und " write " richten die Clusterknoten ein, und die Option " sticky ", die auf " true " gesetzt ist, verwendet " write " - Verbindungen erneut, sodass in die Datenbank geschriebene Daten sofort verfügbar sind gleicher Anforderungszyklus. Sie können den Wert auf " false" setzen, wenn Sie dieses Verhalten nicht möchten.

/var/www/travel_list/config/database.php

...
     'mysql' => [
        'read' => [
          'host' => [
             '',
             '',
          ],
        ],
        'write' => [
          'host' => [
            '',
          ],
        ],
      'sticky' => true,
...

Speichern und schließen Sie die Datei, wenn Sie mit der Bearbeitung fertig sind. Um zu testen, ob alles wie erwartet funktioniert, können wir eine temporäre Route in "+ routes / web.php +" erstellen, um einige Daten aus der Datenbank abzurufen und Details über die verwendete Verbindung anzuzeigen. Auf diese Weise können wir sehen, wie die Anforderungen zwischen den Nur-Lese-Knoten ausgelastet werden.

Öffnen Sie die Datei + routes / web.php +:

nano routes/web.php

Fügen Sie die folgende Route hinzu:

/var/www/travel_list/routes/web.php

...

Route::get('/mysql-test', function () {
 $places = App\Place::all();
 $results = DB::select( DB::raw("SHOW VARIABLES LIKE 'server_id'") );

 return "Server ID: " . $results[0]->Value;
});

Rufen Sie nun Ihren Browser auf und rufen Sie die Anwendungsroute "+ / mysql-test +" auf:

http:///mysql-test

Sie sehen eine Seite wie diese:

image: https: //assets.digitalocean.com/articles/laravel_at_scale/mysql_test_page.png [mysql node test page]

Laden Sie die Seite einige Male neu, und Sie werden feststellen, dass sich der Wert "+ Server ID +" ändert, was darauf hinweist, dass die Anforderungen zufällig auf die beiden schreibgeschützten Knoten verteilt werden.

Fazit

In diesem Handbuch haben wir eine Laravel 6-Anwendung für eine hochverfügbare und skalierbare Umgebung vorbereitet. Wir haben das Datenbanksystem an einen extern verwalteten MySQL-Dienst ausgelagert und einen S3-kompatiblen Objektspeicherdienst in die Anwendung integriert, um von Benutzern hochgeladene Dateien zu speichern. Schließlich haben wir gesehen, wie Sie die Datenbank der Anwendung skalieren können, indem Sie zusätzliche schreibgeschützte Cluster-Knoten in die Konfigurationsdatei der App aufnehmen.

Den aktualisierten Demoanwendungscode mit allen in diesem Handbuch vorgenommenen Änderungen finden Sie unter 2.1 tag im Repository der Anwendung auf Github.

Von hier aus können Sie eine Load Balancer einrichten, um die Last zu verteilen und Ihre Anwendung auf mehrere Knoten zu skalieren. Sie können dieses Setup auch nutzen, um eine containerized environment zu erstellen, um Ihre Anwendung in Docker auszuführen.