管理対象データベースとオブジェクトストレージを使用してスケーラブルなLaravel6アプリケーションをセットアップする方法
序章
Webアプリケーションを水平方向にスケーリングする場合、通常直面する最初の問題は、ファイルストレージとデータの永続性の処理です。 これは主に、複数のアプリケーションノード間で可変データの一貫性を維持することが難しいという事実によるものです。 あるノードで作成されたデータをクラスター内の他のノードですぐに利用できるようにするには、適切な戦略を立てる必要があります。
整合性の問題を解決する実際的な方法は、管理対象データベースおよびオブジェクトストレージシステムを使用することです。 前者はデータの永続性を管理対象データベースにアウトソーシングし、後者は静的ファイルやユーザーがアップロードした画像などの可変コンテンツを保持できるリモートストレージサービスを提供します。 その後、各ノードはアプリケーションレベルでこれらのサービスに接続できます。
次の図は、PHPアプリケーションのコンテキストで、このようなセットアップを水平方向のスケーラビリティーに使用する方法を示しています。
このガイドでは、既存のLaravel 6アプリケーションを更新して、管理対象のMySQLデータベースに接続し、ユーザーが生成したファイルを保存するようにS3互換のオブジェクトストアを設定することで、水平方向のスケーラビリティに備えます。 最終的に、Nginx +PHP-FPMWebサーバーで旅行リストアプリケーションを実行できるようになります。
注:このガイドでは、 DigitalOcean ManagedMySQLおよびSpacesを使用して、管理対象データベースとオブジェクトストレージを使用したスケーラブルなアプリケーションセットアップを示します。 ここに含まれる手順は、他のサービスプロバイダーでも同様に機能するはずです。
前提条件
このチュートリアルを開始するには、最初に次の前提条件が必要です。
- sudo権限を持つ非rootユーザーとしてUbuntu18.04サーバーにアクセスし、サーバーにアクティブなファイアウォールをインストールします。 これらを設定するには、 Ubuntu18.04の初期サーバー設定ガイドを参照してください。
- Ubuntu18.04にLEMPをインストールする方法の手順1および3で説明されているように、NginxおよびPHP-FPMがサーバーにインストールおよび構成されています。 MySQLがインストールされているステップはスキップする必要があります。
- Ubuntu18.04にComposerをインストールして使用する方法の手順1および2で説明されているように、サーバーにComposerがインストールされています。
- 管理対象のMySQL8データベースへの管理者クレデンシャル。 このガイドでは、 DigitalOcean Managed MySQL クラスターを使用しますが、ここでの手順は、他のマネージドデータベースサービスでも同様に機能するはずです。
- S3互換のオブジェクトストレージサービスへの読み取りおよび書き込み権限を持つAPIキーのセット。 このガイドでは、 DigitalOcean Spaces を使用しますが、選択したプロバイダーを自由に使用できます。
- The
s3cmd
オブジェクトストレージドライブに接続するためにインストールおよび構成されたツール。 DigitalOcean Spacesでこれを設定する方法については、製品ドキュメントを参照してください。
ステップ1—MySQL8クライアントのインストール
デフォルトのUbuntuaptリポジトリにはMySQL5クライアントが付属していますが、これはこのガイドで使用するMySQL8サーバーと互換性がありません。 互換性のあるMySQLクライアントをインストールするには、Oracleが提供するMySQLAPTリポジトリを使用する必要があります。
WebブラウザのMySQLAPTリポジトリページに移動することから始めます。 右下隅にあるダウンロードボタンを見つけて、クリックして次のページに進みます。 このページでは、OracleWebアカウントにログインまたはサインアップするように求められます。 それをスキップして、代わりにというリンクを探すことができます。いいえ、ダウンロードを開始してください。 リンクアドレスをコピーして、ターミナルウィンドウに戻ります。
このリンクは .deb
サーバーにMySQLAPTリポジトリをセットアップするパッケージ。 インストール後、ご利用いただけるようになります apt
MySQLの最新リリースをインストールします。 使用します curl
このファイルを一時的な場所にダウンロードします。
サーバーに移動します tmp
フォルダ:
- cd /tmp
今すぐパッケージをダウンロードしてください curl
MySQLAPTリポジトリページからコピーしたURLを使用します。
- curl -OL https://dev.mysql.com/get/mysql-apt-config_0.8.13-1_all.deb
ダウンロード終了後、ご利用いただけます dpkg
パッケージをインストールするには:
- sudo dpkg -i mysql-apt-config_0.8.13-1_all.deb
デフォルトとして選択するMySQLバージョンと、関心のあるMySQLコンポーネントを選択できる画面が表示されます。
デフォルトのオプションでは必要なリポジトリがインストールされるため、ここでは何も変更する必要はありません。 「OK」を選択すると、設定が完了します。
次に、更新する必要があります apt
キャッシュ:
- sudo apt update
これで、最終的にMySQL8クライアントを次のようにインストールできます。
- sudo apt install mysql-client
そのコマンドが終了したら、ソフトウェアのバージョン番号をチェックして、最新のリリースであることを確認します。
- mysql --version
次のような出力が表示されます。
Outputmysql Ver 8.0.18 for Linux on x86_64 (MySQL Community Server - GPL)
次のステップでは、MySQLクライアントを使用して管理対象のMySQLサーバーに接続し、アプリケーション用のデータベースを準備します。
ステップ2—新しいMySQLユーザーとデータベースを作成する
この記事の執筆時点では、ネイティブMySQLPHPライブラリ mysqlnd
はサポートしていません caching_sha2_authentication
、MySQL8のデフォルトの認証方法。 を使用して新しいユーザーを作成する必要があります mysql_native_password
LaravelアプリケーションをMySQL8サーバーに接続できるようにするための認証方法。 また、デモアプリケーション専用のデータベースを作成します。
開始するには、管理者アカウントを使用してサーバーにログインします。 強調表示された値を独自のMySQLユーザー、ホスト、およびポートに置き換えます。
- mysql -u MYSQL_USER -p -h MYSQL_HOST -P MYSQL_PORT
プロンプトが表示されたら、管理者ユーザーのパスワードを入力します。 ログインすると、MySQL8サーバーのコマンドラインインターフェイスにアクセスできるようになります。
まず、アプリケーション用の新しいデータベースを作成します。 次のコマンドを実行して、という名前の新しいデータベースを作成します travellist
:
- CREATE DATABASE travellist;
次に、新しいユーザーを作成し、を使用してパスワードを設定します mysql_native_password
このユーザーのデフォルトの認証方法として。 強調表示された値を独自の値に置き換え、強力なパスワードを使用することをお勧めします。
- CREATE USER 'travellist-user'@'%' IDENTIFIED WITH mysql_native_password BY 'MYSQL_PASSWORD';
次に、アプリケーションデータベースに対するこのユーザー権限を付与する必要があります。
- GRANT ALL ON travellist.* TO 'travellist-user'@'%';
これで、次のコマンドでMySQLプロンプトを終了できます。
- exit;
これで、Laravelアプリケーションから接続するための専用データベースと互換性のあるユーザーができました。 次のステップでは、アプリケーションコードを取得して構成の詳細を設定し、アプリが管理対象のMySQLデータベースに接続できるようにします。
このガイドでは、 LaravelMigrationsとデータベースシードを使用してアプリケーションテーブルを設定します。 既存のローカルデータベースをDigitalOceanマネージドMySQLデータベースに移行する必要がある場合は、MySQLデータベースをDigitalOceanマネージドデータベースにインポートする方法に関するドキュメントを参照してください。
ステップ3—デモアプリケーションのセットアップ
開始するには、デモLaravelアプリケーションをGithubリポジトリからフェッチします。 次のコマンドを実行する前に、アプリケーションの内容を自由に調べてください。
デモアプリケーションは、 Ubuntu18.04でLEMPを使用してLaravelをインストールおよび構成する方法に関するガイドで最初に開発されたトラベルバケットリストアプリです。 更新されたアプリには、訪問者がアップロードできる旅行写真や世界地図などの視覚的な改善が含まれています。 また、データベース移行スクリプトとデータベースシードを導入して、アプリケーションテーブルを作成し、それらにサンプルデータを入力します。 artisan
コマンド。
このチュートリアルと互換性のあるアプリケーションコードを入手するには、Githubのプロジェクトのリポジトリから1.1リリースをダウンロードします。 ダウンロードしたzipファイルを次のように保存します travellist.zip
ホームディレクトリ内:
- cd ~
- curl -L https://github.com/do-community/travellist-laravel-demo/archive/1.1.zip -o travellist.zip
次に、アプリケーションのコンテンツを解凍し、ディレクトリの名前を次のように変更します。
- unzip travellist.zip
- mv travellist-laravel-demo-1.1 travellist
に移動します travellist
ディレクトリ:
- cd travellist
先に進む前に、Laravelフレームワークに必要ないくつかのPHPモジュールをインストールする必要があります。 php-xml
, php-mbstring
, php-xml
と php-bcmath
. これらのパッケージをインストールするには、以下を実行します。
- sudo apt install unzip php-xml php-mbstring php-xml php-bcmath
アプリケーションの依存関係をインストールするには、次のコマンドを実行します。
- composer install
次のような出力が表示されます。
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.
これで、アプリケーションの依存関係がインストールされました。 次に、管理対象のMySQLデータベースに接続するようにアプリケーションを構成します。
の作成 .env
設定ファイルとアプリキーの設定
次に、 .env
環境ごとにLaravelアプリケーションを構成するために使用される変数を含むファイル。 アプリケーションには、環境設定を反映するように値をコピーして変更できるサンプルファイルが含まれています。
をコピーします .env.example
ファイルを名前の付いた新しいファイルに .env
:
- cp .env.example .env
次に、アプリケーションキーを設定する必要があります。 このキーはセッションデータの暗号化に使用され、32文字の一意の文字列に設定する必要があります。 このキーは、 artisan
道具:
- php artisan key:generate
環境構成ファイルを編集して、データベースの詳細を設定しましょう。 を開きます .env
選択したコマンドラインエディタを使用してファイルを作成します。 ここでは、 nano
:
- nano .env
データベースクレデンシャルセクションを探します。 次の変数には注意が必要です。
DB_HOST
:管理対象のMySQLサーバーホスト。 DB_PORT
:管理対象のMySQLサーバーポート。 DB_DATABASE
:ステップ2で作成したアプリケーションデータベースの名前。 DB_USERNAME
:ステップ2で作成したデータベースユーザー。 DB_PASSWORD
:ステップ2で定義したデータベースユーザーのパスワード。
強調表示された値を独自の管理対象MySQL情報とクレデンシャルで更新します。
...
DB_CONNECTION=mysql
DB_HOST=MANAGED_MYSQL_HOST
DB_PORT=MANAGED_MYSQL_PORT
DB_DATABASE=MANAGED_MYSQL_DB
DB_USERNAME=MANAGED_MYSQL_USER
DB_PASSWORD=MANAGED_MYSQL_PASSWORD
...
次のように入力して、ファイルを保存して閉じます CTRL+X
それから Y
と ENTER
編集が終わったら。
アプリケーションがMySQLデータベースに接続するように構成されたので、Laravelのコマンドラインツールを使用できます artisan
データベーステーブルを作成し、サンプルデータを入力します。
ストレージリンクの設定
によって提供されるデータベースツールを実行する前に artisan
コマンドを実行するには、アプリケーションで使用している旅行の写真をホストするパブリックストレージフォルダーへのシンボリックリンクを作成する必要があります。 これが必要なのは、データベースシードスクリプトがこれらのサンプル写真に依存してデータを挿入するためです。 places
テーブル。
次のコマンドは、内部にシンボリックリンクを作成します public
ディレクトリ。Webサーバーを介して公開され、アプリケーションの内部ストレージディレクトリを指します。 storage/app/public
:
- php artisan storage:link
OutputThe [public/storage] directory has been linked.
リンクが作成され、それが指している場所を確認するには、次のコマンドを実行します。
- ls -la public/
次のような出力が表示されます。
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
lrwxrwxrwx 1 sammy sammy 41 Oct 25 14:59 storage -> /home/sammy/travellist/storage/app/public
-rw-rw-r-- 1 sammy sammy 1194 Oct 25 06:29 web.config
データベースの移行と入力
次に、 LaravelMigrationsとデータベースシードを使用してアプリケーションテーブルを設定します。 これは、データベース構成が期待どおりに機能するかどうかを判断するのに役立ちます。
アプリケーションが使用するテーブルを作成する移行スクリプトを実行するには、次のコマンドを実行します。
- php artisan migrate
次のような出力が表示されます。
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)
データベースにサンプルデータを入力するには、次のコマンドを実行します。
- php artisan db:seed
次のような出力が表示されます。
OutputSeeding: PlacesTableSeeder
Seeded: PlacesTableSeeder (0.86 seconds)
Database seeding completed successfully.
これで、アプリケーションテーブルが作成され、サンプルデータが入力されます。
テストサーバーの実行(オプション)
あなたは使用することができます artisan serve
長期間アプリケーションにサービスを提供するためにNginxなどのフル機能のWebサーバーを構成する前に、アプリケーション内ですべてが正しくセットアップされていることをすばやく確認するコマンド。
ポートを使用します 8000
テスト用のアプリケーションを一時的に提供します。 サーバーでUFWファイアウォールを有効にしている場合は、最初に次の方法でこのポートへのアクセスを許可する必要があります。
- sudo ufw allow 8000
次に、Laravelが公開する組み込みのPHPサーバーを実行します。 artisan
ツール、実行:
- php artisan serve --host=0.0.0.0 --port=8000
このコマンドは、で中断されるまで端末をブロックします CTRL+C
. 組み込みのPHPWebサーバーを使用して、ポートを使用し、すべてのネットワークインターフェイスでテスト目的でアプリケーションを提供します。 8000
.
次に、ブラウザに移動し、ポートのサーバーのドメイン名またはIPアドレスを使用してアプリケーションにアクセスします 8000
:
http://server_domain_or_IP:8000
次のページが表示されます。
このページが表示されている場合は、アプリケーションが構成済みの管理対象データベースから場所と写真に関するデータを正常に取得していることを意味します。 イメージファイルは引き続きローカルディスクに保存されますが、このガイドの次の手順で変更します。
アプリケーションのテストが終了したら、停止できます serve
を押すことによるコマンド CTRL+C
.
ポートを閉じることを忘れないでください 8000
サーバーでUFWを実行している場合も、次のようになります。
- sudo ufw deny 8000
ステップ4—アプリケーションにサービスを提供するようにNginxを構成する
組み込みのPHPWebサーバーは、開発とテストの目的で非常に役立ちますが、PHPアプリケーションを提供するための長期的なソリューションとして使用することを目的としたものではありません。 Nginxのようなフル機能のWebサーバーを使用することをお勧めします。
開始するには、アプリケーションフォルダをに移動します /var/www
、これはNginxで実行されているWebアプリケーションの通常の場所です。 まず、 mv
アプリケーションフォルダとそのすべての内容をに移動するコマンド /var/www/travellist
:
- sudo mv ~/travellist /var/www/travellist
次に、Webサーバーユーザーに書き込みアクセス権を付与する必要があります。 storage
と bootstrap/cache
Laravelがアプリケーションで生成されたファイルを保存するフォルダー。 これらの権限は、を使用して設定します setfacl
、ファイルやフォルダでより堅牢できめ細かい権限設定を可能にするコマンドラインユーティリティ。
必要なディレクトリに対するWebサーバーユーザーへの読み取り、書き込み、および実行(rwx)権限を含めるには、次のコマンドを実行します。
- 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
これでアプリケーションファイルは正常になりましたが、コンテンツを提供するようにNginxを構成する必要があります。 これを行うには、次の場所に新しい仮想ホスト構成ファイルを作成します。 /etc/nginx/sites-available
:
- sudo nano /etc/nginx/sites-available/travellist
次の構成ファイルには、Nginx上のLaravelアプリケーションの推奨設定が含まれています。
server {
listen 80;
server_name server_domain_or_IP;
root /var/www/travellist/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;
}
}
このコンテンツをあなたの /etc/nginx/sites-available/travellist
ファイルを作成し、強調表示された値を調整して、独自の構成に合わせます。 編集が完了したら、ファイルを保存して閉じます。
新しい仮想ホスト構成ファイルをアクティブ化するには、次のシンボリックリンクを作成します。 travellist
の sites-enabled
:
- sudo ln -s /etc/nginx/sites-available/travellist /etc/nginx/sites-enabled/
注:以前に同じように構成された別の仮想ホストファイルがある場合 server_name
で使用される travellist
仮想ホストの場合、内部の対応するシンボリックリンクを削除して、古い構成を非アクティブ化する必要がある場合があります /etc/nginx/sites-enabled/
.
構成に構文エラーが含まれていないことを確認するには、次を使用できます。
- sudo nginx -t
次のような出力が表示されます。
- Outputnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
- nginx: configuration file /etc/nginx/nginx.conf test is successful
変更を適用するには、次のコマンドでNginxをリロードします。
- sudo systemctl reload nginx
ここでブラウザをリロードすると、アプリケーションの画像が壊れます。 これは、アプリケーションディレクトリをサーバー内の新しい場所に移動したために発生します。そのため、アプリケーションストレージフォルダへのシンボリックリンクを再作成する必要があります。
次のコマンドで古いリンクを削除します。
- cd /var/www/travellist
- rm -f public/storage
今もう一度実行します artisan
ストレージリンクを生成するコマンド:
- php artisan storage:link
次に、ブラウザに移動し、サーバーのドメイン名またはIPアドレスを使用してアプリケーションにアクセスします。 server_name
構成ファイルのディレクティブ:
http://server_domain_or_IP
次のステップでは、オブジェクトストレージサービスをアプリケーションに統合します。 これにより、旅行の写真に使用されている現在のローカルディスクストレージが置き換えられます。
ステップ5—S3互換のオブジェクトストレージをアプリケーションに統合する
次に、S3互換のオブジェクトストレージサービスを使用して、インデックスページに表示された旅行の写真を保存するようにアプリケーションを設定します。 アプリケーションにはすでにローカルディスクに保存されているサンプル写真がいくつかあるため、 s3cmd ツールを使用して、既存のローカル画像ファイルをリモートオブジェクトストレージにアップロードします。
Laravel用のS3ドライバーのセットアップ
Laravelは league/flysystem
、Laravelアプリケーションがローカルディスクやクラウドサービスを含む複数のストレージソリューションを使用および組み合わせることができるようにするファイルシステム抽象化ライブラリ。 を使用するには、追加のパッケージが必要です s3
運転者。 このパッケージは、 composer require
指図。
アプリケーションディレクトリにアクセスします。
- cd /var/www/travellist
- composer require league/flysystem-aws-s3-v3
次のような出力が表示されます。
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
...
必要なパッケージがインストールされたので、アプリケーションを更新してオブジェクトストレージに接続できます。 まず、 .env
ファイルを再度ファイルして、オブジェクトストレージサービスのキー、バケット名、リージョンなどの構成の詳細を設定します。
を開きます .env
ファイル:
- nano .env
次の環境変数を含め、強調表示された値をオブジェクトストア構成の詳細に置き換えます。
DO_SPACES_KEY=EXAMPLE7UQOTHDTF3GK4
DO_SPACES_SECRET=exampleb8e1ec97b97bff326955375c5
DO_SPACES_ENDPOINT=https://ams3.digitaloceanspaces.com
DO_SPACES_REGION=ams3
DO_SPACES_BUCKET=sammy-travellist
完了したら、ファイルを保存して閉じます。 今すぐ開きます config/filesystems.php
ファイル:
- nano config/filesystems.php
このファイル内に、新しいdiskエントリを作成します。 disks
配列。 このディスクに名前を付けます spaces
、で設定した環境変数を使用します .env
新しいディスクを構成するファイル。 次のエントリをに含めます disks
配列:
'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'),
],
同じファイルで、 cloud
エントリを変更して、新しいものを設定します spaces
デフォルトのクラウドファイルシステムディスクとしてのディスク:
'cloud' => env('FILESYSTEM_CLOUD', 'spaces'),
編集が完了したら、ファイルを保存して閉じます。 これで、コントローラーから、 Storage::cloud()
デフォルトにアクセスするためのショートカットとしてのメソッド cloud
ディスク。 このように、アプリケーションは複数のストレージソリューションを使用する柔軟性を維持し、環境ごとにプロバイダーを切り替えることができます。
これで、アプリケーションはオブジェクトストレージを使用するように構成されましたが、新しい写真をアプリケーションにアップロードするコードを更新する必要があります。
まず、現在の状況を調べてみましょう uploadPhoto
ルート、にあります PhotoController
クラス。 テキストエディタを使用してファイルを開きます。
- nano 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->image = $request->image->store('/', 'public');
$photo->save();
return redirect()->route('Main');
}
このメソッドは、 POST
リクエストして、写真テーブルに新しい写真エントリを作成します。 まず、写真アップロードフォームで既存の場所が選択されているかどうかを確認します。選択されていない場合は、提供された情報を使用して新しい場所を作成します。 その後、場所はに設定されます visited
そしてデータベースに保存されます。 その後、新しい写真が指定された場所にリンクされるように関連付けが作成されます。 その後、画像ファイルはのルートフォルダに保存されます public
ディスク。 最後に、写真がデータベースに保存されます。 次に、ユーザーは、アプリケーションのインデックスページであるメインルートにリダイレクトされます。
このコードで強調表示されている行は、私たちが関心を持っているものです。 その行で、イメージファイルはを使用してディスクに保存されます store
方法。 The store
メソッドは、で定義されたディスクのいずれかにファイルを保存するために使用されます filesystem.php
構成ファイル。 この場合、アップロードされた画像を保存するためにデフォルトのディスクを使用しています。
この動作を変更して、イメージがローカルディスクではなくオブジェクトストアに保存されるようにします。 そのためには、 public
ディスクによる spaces
のディスク store
メソッド呼び出し。 また、アップロードされたファイルの可視性がprivateではなくpublicに設定されていることを確認する必要があります。
次のコードには完全なものが含まれています PhotoController
更新されたものを含むクラス uploadPhoto
方法:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Photo;
use App\Place;
use Illuminate\Support\Facades\Storage;
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->image = $request->image->store('/', 'spaces');
Storage::setVisibility($photo->image, 'public');
$photo->save();
return redirect()->route('Main');
}
}
更新されたコードを自分のコードにコピーします PhotoController
強調表示された変更を反映するようにします。 編集が完了したら、ファイルを保存して閉じます。
アプリケーションのメインビューを変更して、オブジェクトストレージファイルのURLを使用して画像をレンダリングする必要があります。 を開きます travel_list.blade.php
テンプレート:
- nano resources/views/travel_list.blade.php
次に、 footer
ページのセクション。現在、次のようになっています。
@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="{{ asset('storage') . '/' . $photo->image }}" />
<p>{{ $photo->place->name }}</p>
</div>
@endforeach
@endsection
現在の画像を置き換える src
からのファイルURLを使用する属性 spaces
ストレージディスク:
<img src="{{ Storage::disk('spaces')->url($photo->image) }}" />
今すぐブラウザにアクセスしてアプリケーションページをリロードすると、壊れた画像のみが表示されます。 これは、これらの旅行写真の画像ファイルがまだローカルディスクにのみ存在するために発生します。 データベースにすでに保存されている写真をアプリケーションページに正常に表示できるように、既存の画像ファイルをオブジェクトストレージにアップロードする必要があります。
ローカル画像との同期 s3cmd
The s3cmd
ツールを使用して、ローカルファイルをS3互換のオブジェクトストレージサービスと同期できます。 実行します sync
内部のすべてのファイルをアップロードするコマンド storage/app/public/photos
オブジェクトストレージサービスに。
アクセスする public
アプリのストレージディレクトリ:
- cd /var/www/travellist/storage/app/public
リモートディスクにすでに保存されているファイルを確認するには、 s3cmd ls
指図:
- s3cmd ls s3://your_bucket_name
今実行します sync
パブリックストレージフォルダ内の既存のファイルをオブジェクトストレージにアップロードするコマンド:
- s3cmd sync ./ s3://your_bucket_name --acl-public --exclude=.gitignore
これにより、現在のフォルダが同期されます(storage/app/public
)リモートオブジェクトストレージのルートディレクトリを使用します。 次のような出力が得られます。
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.
今、あなたが実行すると s3cmd ls
ここでも、オブジェクトストレージバケットのルートフォルダに3つの新しいファイルが追加されたことがわかります。
- s3cmd ls s3://your_bucket_name
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
ブラウザに移動して、アプリケーションページをリロードします。 これですべての画像が表示されるはずです。ブラウザのデバッグツールを使用して画像を調べると、すべての画像がオブジェクトストレージのURLを使用していることがわかります。
統合のテスト
これで、デモアプリケーションは完全に機能し、リモートオブジェクトストレージサービスにファイルを保存し、管理対象のMySQLデータベースにデータを保存します。 これで、セットアップをテストするためにいくつかの写真をアップロードできます。
アクセスする /upload
ブラウザからのアプリケーションルート:
http://server_domain_or_IP/upload
次のフォームが表示されます。
これで、いくつかの写真をアップロードして、オブジェクトストレージの統合をテストできます。 コンピューターから画像を選択した後、ドロップダウンメニューから既存の場所を選択するか、名前と地理座標を指定して新しい場所を追加し、アプリケーションマップに読み込むことができます。
ステップ6—読み取り専用ノードを使用したDigitalOceanマネージドMySQLデータベースのスケールアップ(オプション)
通常、読み取り専用操作はデータベースサーバーでの書き込み操作よりも頻繁に行われるため、複数の読み取り専用ノードを設定してデータベースクラスターをスケールアップするのが一般的な方法です。 これにより、によって生成された負荷が分散されます SELECT
オペレーション。
このセットアップを示すために、最初に2つの読み取り専用ノードをDigitalOceanマネージドMySQLクラスターに追加します。 次に、これらのノードを使用するようにLaravelアプリケーションを構成します。
DigitalOcean Cloud Panel にアクセスし、次の手順に従います。
- データベースに移動し、MySQLクラスターを選択します。
- クリック
Actions
と選択しますAdd a read-only node
ドロップダウンメニューから。 - ノードオプションを設定し、作成ボタンを押します。 新しいノードの準備ができるまでに数分かかる場合があることに注意してください。
- 手順1〜4をもう一度繰り返して、読み取り専用ノードを2つ作成します。
- Laravel構成で必要になるため、2つのノードのホストを書き留めます。
読み取り専用ノードの準備ができたら、ターミナルに戻ります。
次に、複数のデータベースノードで動作するようにLaravelアプリケーションを構成します。 終了したら、次のようなクエリ INSERT
と UPDATE
すべてがプライマリクラスタノードに転送されます SELECT
クエリは読み取り専用ノードにリダイレクトされます。
まず、サーバー上のアプリケーションのディレクトリに移動し、 .env
選択したテキストエディタを使用したファイル:
- cd /var/www/travellist
- nano .env
MySQLデータベース構成を見つけて、コメントアウトします。 DB_HOST
ライン:
DB_CONNECTION=mysql
#DB_HOST=MANAGED_MYSQL_HOST
DB_PORT=MANAGED_MYSQL_PORT
DB_DATABASE=MANAGED_MYSQL_DB
DB_USERNAME=MANAGED_MYSQL_USER
DB_PASSWORD=MANAGED_MYSQL_PASSWORD
完了したら、ファイルを保存して閉じます。 今すぐ開きます config/database.php
テキストエディタで:
- nano config/database.php
探してください mysql
内部のエントリ connections
配列。 この構成配列に3つの新しいアイテムを含める必要があります。 read
, write
、 と sticky
. The read
と write
エントリはクラスタノードを設定し、 sticky
オプションをに設定 true
再利用します write
データベースに書き込まれたデータが同じ要求サイクルですぐに利用できるようにするための接続。 あなたはそれを設定することができます false
この動作を望まない場合。
...
'mysql' => [
'read' => [
'host' => [
'READONLY_NODE1_HOST',
'READONLY_NODE2_HOST',
],
],
'write' => [
'host' => [
'MANAGED_MYSQL_HOST',
],
],
'sticky' => true,
...
編集が完了したら、ファイルを保存して閉じます。 すべてが期待どおりに機能することをテストするために、内部に一時的なルートを作成できます routes/web.php
データベースからいくつかのデータをプルし、使用されている接続に関する詳細を表示します。 このようにして、読み取り専用ノード間でリクエストがどのように負荷分散されているかを確認できます。
を開きます routes/web.php
ファイル:
- nano 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;
});
次に、ブラウザに移動して、 /mysql-test
アプリケーションルート:
http://server_domain_or_IP/mysql-test
次のようなページが表示されます。
ページを数回リロードすると、 Server ID
値が変化し、リクエストが2つの読み取り専用ノード間でランダムに分散されていることを示します。
結論
このガイドでは、高可用性でスケーラブルな環境向けのLaravel6アプリケーションを用意しました。 データベースシステムを外部のマネージドMySQLサービスにアウトソーシングし、S3互換のオブジェクトストレージサービスをアプリケーションに統合して、ユーザーがアップロードしたファイルを保存しました。 最後に、アプリの構成ファイルに追加の読み取り専用クラスターノードを含めることで、アプリケーションのデータベースをスケールアップする方法を確認しました。
このガイドで行われたすべての変更を含む更新されたデモアプリケーションコードは、Githubのアプリケーションのリポジトリにある2.1タグ内にあります。
ここから、ロードバランサーをセットアップして、負荷を分散し、アプリケーションを複数のノードにスケーリングできます。 この設定を利用して、コンテナー化された環境を作成し、Dockerでアプリケーションを実行することもできます。