Cách thiết lập ứng dụng Laravel 6 có thể mở rộng bằng cách sử dụng dịch vụ database và Lưu trữ đối tượng
Khi mở rộng các ứng dụng web theo chiều ngang, những khó khăn đầu tiên bạn thường gặp phải là giải quyết vấn đề lưu trữ file và tính liên tục của dữ liệu. Điều này chủ yếu là do thực tế là khó duy trì tính nhất quán của dữ liệu biến đổi giữa nhiều nút ứng dụng; các chiến lược thích hợp phải được đưa ra đảm bảo dữ liệu được tạo trong một nút có sẵn ngay lập tức cho các node khác trong một cụm.Một cách thực tế để giải quyết vấn đề nhất quán là sử dụng dịch vụdatabase và hệ thốnglưu trữ đối tượng . Đầu tiên sẽ thuê ngoài sự bền vững của dữ liệu cho database được quản lý và thứ sau sẽ cung cấp dịch vụ lưu trữ từ xa, nơi bạn có thể giữ các file tĩnh và nội dung biến đổi như hình ảnh do user tải lên. Mỗi nút sau đó có thể kết nối với các dịch vụ này ở cấp ứng dụng.
Sơ đồ sau minh họa cách cài đặt như vậy được dùng cho khả năng mở rộng theo chiều ngang trong ngữ cảnh của các ứng dụng PHP:
Trong hướng dẫn này, ta sẽ cập nhật ứng dụng Laravel 6 hiện có để chuẩn bị cho nó khả năng mở rộng theo chiều ngang bằng cách kết nối nó với database MySQL được quản lý và cài đặt kho đối tượng tương thích S3 để lưu các file do user tạo. Cuối cùng, bạn sẽ có một ứng dụng danh sách du lịch chạy trên web server Nginx + PHP-FPM:
 Lưu ý : hướng dẫn này sử dụng DigitalOcean Managed MySQL và Spaces để chứng minh  cài đặt  ứng dụng có thể mở rộng bằng cách sử dụng database  được quản lý và lưu trữ đối tượng. Các hướng dẫn ở đây sẽ hoạt động theo cách tương tự đối với các nhà cung cấp dịch vụ khác.
Yêu cầu
Để bắt đầu hướng dẫn này, trước tiên bạn cần các yêu cầu sau:
- Truy cập vào server Ubuntu 18.04 với quyền là user không phải root có quyền sudo và firewall hoạt động được cài đặt trên server của bạn. Để cài đặt những điều này, vui lòng tham khảo Hướng dẫn Cài đặt Server Ban đầu cho Ubuntu 18.04 của ta .
 - Nginx và PHP-FPM được cài đặt và cấu hình trên server của bạn, như được giải thích trong bước 1 và 3 của Cách cài đặt LEMP trên Ubuntu 18.04 . Bạn nên bỏ qua bước cài đặt MySQL.
 - Composer được cài đặt trên server của bạn, như được giải thích trong bước 1 và 2 của Cách cài đặt và sử dụng Composer trên Ubuntu 18.04 .
 - Thông tin đăng nhập administrator đối với database MySQL 8 được quản lý. Đối với hướng dẫn này, ta sẽ sử dụng cụm DigitalOcean Managed MySQL , nhưng các hướng dẫn ở đây sẽ hoạt động tương tự đối với các dịch vụ database được quản lý khác.
 - Một tập hợp các khóa API có quyền đọc và ghi đối với dịch vụ lưu trữ đối tượng tương thích với S3. Trong hướng dẫn này, ta sẽ sử dụng DigitalOcean Spaces , nhưng bạn có thể tự do sử dụng nhà cung cấp mà bạn chọn.
 -  Công cụ 
s3cmdđã được cài đặt và cấu hình để kết nối với ổ lưu trữ đối tượng của bạn. Để biết hướng dẫn về cách cài đặt điều này cho DigitalOcean Spaces, vui lòng tham khảo tài liệu sản phẩm của ta . 
Bước 1 - Cài đặt Máy khách MySQL 8
Kho lưu trữ apt Ubuntu mặc định đi kèm với client MySQL 5, không tương thích với server MySQL 8 mà ta sẽ sử dụng trong hướng dẫn này. Để cài đặt ứng dụng client MySQL tương thích, ta cần sử dụng Kho lưu trữ APT của MySQL do Oracle cung cấp.
Bắt đầu bằng cách chuyển đến trang Kho lưu trữ APT MySQL trong trình duyệt web . Tìm nút Download ở góc dưới bên phải và nhấp qua trang tiếp theo. Trang này sẽ nhắc bạn đăng nhập hoặc đăng ký account web Oracle. Bạn có thể bỏ qua điều đó và thay vào đó hãy tìm liên kết có nội dung Không, cảm ơn, chỉ cần bắt đầu download của tôi . Sao chép địa chỉ liên kết và quay lại cửa sổ dòng lệnh của bạn.
 Liên kết này sẽ trỏ đến một .deb sẽ  cài đặt  Kho lưu trữ APT MySQL trong  server  của bạn. Sau khi cài đặt nó,  bạn có thể  sử dụng apt để cài đặt các bản phát hành mới nhất của MySQL.  Ta  sẽ sử dụng curl để tải file  này xuống một vị trí tạm thời.
 Đi tới folder  tmp của  server  của bạn:
- cd /tmp 
 
Bây giờ  download  gói với curl và sử dụng URL bạn đã sao chép từ trang Kho lưu trữ APT của MySQL:
- curl -OL https://dev.mysql.com/get/mysql-apt-config_0.8.13-1_all.deb 
 
Sau khi  download  xong, bạn có thể sử dụng dpkg để cài đặt gói:
- sudo dpkg -i mysql-apt-config_0.8.13-1_all.deb 
 
Bạn sẽ thấy một màn hình nơi bạn có thể chọn version MySQL nào bạn muốn chọn làm mặc định, cũng như các thành phần MySQL mà bạn quan tâm:
Bạn không cần phải thay đổi bất cứ điều gì ở đây, vì các tùy chọn mặc định sẽ cài đặt kho ta cần. Chọn “Ok” và cấu hình sẽ hoàn tất.
 Tiếp theo, bạn  cần  cập nhật bộ nhớ cache apt  của bạn  bằng:
- sudo apt update 
 
Bây giờ cuối cùng ta có thể cài đặt client MySQL 8 với:
- sudo apt install mysql-client 
 
Sau khi lệnh đó kết thúc, hãy kiểm tra số version phần mềm đảm bảo rằng bạn có bản phát hành mới nhất:
- mysql --version 
 
Bạn sẽ thấy kết quả như thế này:
Outputmysql  Ver 8.0.18 for Linux on x86_64 (MySQL Community Server - GPL) Trong bước tiếp theo, ta sẽ sử dụng client MySQL để kết nối với server MySQL được quản lý của bạn và chuẩn bị database cho ứng dụng.
Bước 2 - Tạo Database và User MySQL mới
 Tại thời điểm viết bài này, thư viện MySQL PHP mysqlnd không hỗ trợ caching_sha2_authentication , phương thức xác thực mặc định cho MySQL 8.  Ta   cần  tạo một  user  mới với phương thức xác thực mysql_native_password để có thể kết nối Laravel của  ta  ứng dụng cho  server  MySQL 8.  Ta  cũng sẽ tạo một database  dành riêng cho ứng dụng demo của  ta .
Để bắt đầu, hãy đăng nhập vào server của bạn bằng account quản trị. Thay thế các giá trị được đánh dấu bằng user , server lưu trữ và cổng MySQL của bạn :
- mysql -u MYSQL_USER -p -h MYSQL_HOST -P MYSQL_PORT 
 
Khi được yêu cầu , hãy cung cấp password của admin-user viên. Sau khi đăng nhập, bạn sẽ có quyền truy cập vào giao diện dòng lệnh của server MySQL 8.
 Đầu tiên,  ta  sẽ tạo một database  mới cho ứng dụng. Chạy lệnh sau để tạo một database  mới có tên travellist :
- CREATE DATABASE travellist; 
 
Tiếp theo,  ta  sẽ tạo một  user  mới và đặt password , sử dụng mysql_native_password làm phương thức xác thực mặc định cho  user  này. Bạn được khuyến khích thay thế các giá trị được đánh dấu bằng các giá trị  của bạn  và sử dụng password  mạnh:
- CREATE USER 'travellist-user'@'%' IDENTIFIED WITH mysql_native_password BY 'MYSQL_PASSWORD'; 
 
Bây giờ ta cần cấp quyền cho user này đối với database ứng dụng của ta :
- GRANT ALL ON travellist.* TO 'travellist-user'@'%'; 
 
Đến đây bạn có thể thoát khỏi dấu nhắc MySQL bằng:
- exit; 
 
Đến đây bạn có một database chuyên dụng và một user tương thích để kết nối từ ứng dụng Laravel của bạn. Trong bước tiếp theo, ta sẽ lấy mã ứng dụng và cài đặt chi tiết cấu hình để ứng dụng của bạn có thể kết nối với database MySQL được quản lý của bạn.
 Trong hướng dẫn này,  ta  sẽ sử dụng Laravel Migrations và các hạt database  để  cài đặt  các bảng ứng dụng của  ta . Nếu bạn cần di chuyển database  local  hiện có sang database  MySQL được quản lý DigitalOcean, vui lòng tham khảo tài liệu của  ta  về Cách nhập  Database  MySQL vào Dịch vụdatabase DigitalOcean .
Bước 3 - Cài đặt ứng dụng Demo
Để bắt đầu, ta sẽ tìm nạp ứng dụng Laravel demo từ kho Github của nó. Hãy kiểm tra nội dung của ứng dụng trước khi chạy các lệnh tiếp theo.
 Ứng dụng demo là một ứng dụng danh sách  group  du lịch ban đầu được phát triển trong hướng dẫn của  ta  về Cách cài đặt và cấu hình Laravel với LEMP trên Ubuntu 18.04 . Ứng dụng được cập nhật hiện có các cải tiến về hình ảnh bao gồm ảnh du lịch mà khách có thể tải lên và bản đồ thế giới. Nó cũng giới thiệu một kịch bản di chuyển database  và các hạt database  để tạo các bảng ứng dụng và đưa chúng vào dữ liệu mẫu, sử dụng các lệnh artisan .
 Để lấy mã ứng dụng tương thích với hướng dẫn này,  ta  sẽ  download  bản phát hành 1.1 từ repository  của dự án trên Github.  Ta  sẽ lưu file  zip đã  download  dưới dạng travellist.zip bên trong folder  chính của  ta :
- cd ~ 
 - curl -L https://github.com/do-community/travellist-laravel-demo/archive/1.1.zip -o travellist.zip 
 
Bây giờ, extract nội dung của ứng dụng và đổi tên folder của nó bằng:
- unzip travellist.zip 
 - mv travellist-laravel-demo-1.1 travellist 
 
Điều hướng đến travellist folder :
- cd travellist 
 
Trước khi tiếp tục,  ta   cần  cài đặt một số module  PHP được yêu cầu bởi khung công tác Laravel, đó là: php-xml , php-mbstring , php-xml và php-bcmath . Để cài đặt các gói này, hãy chạy:
- sudo apt install unzip php-xml php-mbstring php-xml php-bcmath 
 
Để cài đặt các phụ thuộc ứng dụng, hãy chạy:
- composer install 
 
Bạn sẽ thấy kết quả tương tự như sau:
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. Các phụ thuộc ứng dụng hiện đã được cài đặt. Tiếp theo, ta sẽ cấu hình ứng dụng để kết nối với Database MySQL được quản lý.
 Tạo file  cấu hình .env và đặt Khóa ứng dụng
 Bây giờ  ta  sẽ tạo một file  .env chứa các biến sẽ được sử dụng để  cấu hình  ứng dụng Laravel trên cơ sở từng môi trường. Ứng dụng này bao gồm một file  ví dụ mà  ta  có thể sao chép và sau đó sửa đổi các giá trị của nó để phản ánh cài đặt môi trường của  ta .
 Sao chép file  .env.example file  mới có tên .env :
- cp .env.example .env 
 
Bây giờ  ta  cần  cài đặt  khóa ứng dụng. Khóa này được sử dụng để mã hóa dữ liệu phiên và phải được đặt thành một chuỗi dài 32 ký tự duy nhất.  Ta  có thể tạo khóa này tự động bằng artisan cụ artisan công:
- php artisan key:generate 
 
Hãy chỉnh sửa file  cấu hình môi trường để  cài đặt  chi tiết database . Mở file  .env bằng  editor  dòng lệnh mà bạn chọn. Ở đây,  ta  sẽ sử dụng nano :
- nano .env 
 
Tìm phần thông tin database . Các biến sau đây cần bạn chú ý:
 DB_HOST :  server  lưu trữ  server  MySQL được quản lý của bạn.
 DB_PORT : cổng  server  MySQL được quản lý của bạn.
 DB_DATABASE : tên của database  ứng dụng mà  ta  đã tạo ở Bước 2 .
 DB_USERNAME :  user  database  mà  ta  đã tạo ở Bước 2 .
 DB_PASSWORD : password  cho  user  database  mà  ta  đã xác định trong Bước 2 .
Cập nhật các giá trị được đánh dấu bằng thông tin MySQL được quản lý của bạn và bằng chứng xác thực:
... 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 ...  Lưu file    bằng lệnh  CTRL+X rồi đến Y và ENTER khi bạn chỉnh sửa xong.
 Bây giờ mà các ứng dụng được cấu hình để kết nối với database  MySQL,  ta  có thể sử dụng công cụ dòng lệnh Laravel của artisan để tạo ra các bảng database  và cư chúng với dữ liệu mẫu.
Cài đặt liên kết lưu trữ
 Trước khi thực hiện các công cụ database  được cung cấp bởi lệnh artisan ,  ta  cần tạo một  softlink  đến folder  lưu trữ công cộng sẽ lưu trữ các bức ảnh du lịch mà  ta  đang sử dụng trong ứng dụng. Điều này là cần thiết vì tập lệnh hạt giống database  của  ta  dựa vào các ảnh mẫu này để chèn dữ liệu vào bảng places .
 Lệnh sau sẽ tạo một  softlink  bên trong folder  public , được hiển thị công khai thông qua  web server , trỏ đến folder  lưu trữ nội bộ của storage/app/public :
- php artisan storage:link 
 
OutputThe [public/storage] directory has been linked. Để kiểm tra xem liên kết đã được tạo chưa và liên kết trỏ đến, bạn có thể chạy:
- ls -la public/ 
 
Bạn sẽ thấy kết quả như thế này:
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 Di chuyển và đưa vào database
Bây giờ ta sẽ sử dụng Laravel Migrations và các hạt database để cài đặt các bảng ứng dụng. Điều này sẽ giúp ta xác định xem cấu hình database của ta có hoạt động như mong đợi hay không.
Để thực thi tập lệnh di chuyển sẽ tạo các bảng được ứng dụng sử dụng, hãy chạy:
- php artisan migrate 
 
Bạn sẽ thấy kết quả tương tự như sau:
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) Để điền dữ liệu mẫu vào database , hãy chạy:
- php artisan db:seed 
 
Bạn sẽ thấy kết quả như thế này:
OutputSeeding: PlacesTableSeeder Seeded:  PlacesTableSeeder (0.86 seconds) Database seeding completed successfully. Các bảng ứng dụng hiện đã được tạo và điền dữ liệu mẫu.
Chạy server thử nghiệm (tùy chọn)
 Bạn có thể sử dụng lệnh artisan serve để nhanh chóng  xác minh  mọi thứ được  cài đặt  chính xác trong ứng dụng, trước khi phải  cấu hình   web server  đầy đủ tính năng như Nginx để phục vụ ứng dụng trong thời gian dài.
  Ta  sẽ sử dụng cổng 8000 để tạm thời cung cấp ứng dụng để thử nghiệm. Nếu bạn đã bật firewall  UFW trên  server   của bạn , trước tiên bạn nên cho phép truy cập vào cổng này với:
- sudo ufw allow 8000 
 
Bây giờ, để chạy  server  PHP tích hợp sẵn mà Laravel hiển thị thông qua artisan cụ artisan công, hãy chạy:
- php artisan serve --host=0.0.0.0 --port=8000 
 
Lệnh này sẽ chặn terminal  của bạn cho đến khi bị ngắt bằng CTRL+C Nó sẽ sử dụng  web server  PHP tích hợp sẵn để phục vụ ứng dụng cho mục đích thử nghiệm trên tất cả các  network interface , sử dụng cổng 8000 .
 Bây giờ, hãy truy cập trình duyệt của bạn và truy cập ứng dụng bằng domain  hoặc địa chỉ IP của  server  trên cổng 8000 :
http://server_domain_or_IP:8000 Bạn sẽ thấy trang sau:
Nếu bạn thấy trang này, điều đó nghĩa là ứng dụng đang lấy thành công dữ liệu về vị trí và ảnh từ database được quản lý đã cấu hình . Các file hình ảnh vẫn được lưu trữ trong đĩa local , nhưng ta sẽ thay đổi điều này trong bước sau của hướng dẫn này.
 Khi hoàn tất quá trình kiểm tra ứng dụng, bạn có thể dừng lệnh serve bằng cách nhấn CTRL+C
 Đừng quên đóng cổng 8000    nếu bạn đang chạy UFW trên  server   của bạn :
- sudo ufw deny 8000 
 
Bước 4 - Cấu hình Nginx để cung cấp ứng dụng
Mặc dù web server PHP tích hợp sẵn rất hữu ích cho mục đích phát triển và thử nghiệm, nó không được sử dụng như một giải pháp lâu dài để phục vụ các ứng dụng PHP. Sử dụng một web server đầy đủ tính năng như Nginx là cách được khuyến khích để làm điều đó.
 Để bắt đầu,  ta  sẽ di chuyển folder  ứng dụng đến /var/www , đây là vị trí thông thường cho các ứng dụng web chạy trên Nginx. Đầu tiên, sử dụng lệnh mv để di chuyển folder  ứng dụng với tất cả nội dung của nó vào /var/www/travellist :
- sudo mv ~/travellist /var/www/travellist 
 
Bây giờ  ta  cần cấp cho  user   web server  quyền ghi vào các folder  storage và bootstrap/cache , nơi Laravel lưu trữ các file  do ứng dụng tạo.  Ta  sẽ đặt các quyền này bằng setfacl , một tiện ích dòng lệnh cho phép cài đặt quyền chi tiết và mạnh mẽ hơn trong các file  và folder .
Để bao gồm quyền đọc, ghi và thực thi (rwx) cho user web server trên các folder bắt buộc, hãy chạy:
- 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 
 
Các file  ứng dụng hiện đã được sắp xếp theo thứ tự, nhưng  ta  vẫn cần  cấu hình  Nginx để phân phát nội dung. Để thực hiện việc này,  ta  sẽ tạo một file  cấu hình  server  ảo mới tại /etc/nginx/sites-available :
- sudo nano /etc/nginx/sites-available/travellist 
 
Tệp cấu hình sau chứa các cài đặt được đề xuất cho các ứng dụng Laravel trên Nginx:
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;     } } Sao chép nội dung này vào file  /etc/nginx/sites-available/ travellist và điều chỉnh các giá trị được đánh dấu để phù hợp với cấu hình  của bạn .  Lưu file   khi bạn chỉnh sửa xong.
 Để kích hoạt các  file  cấu hình  server  ảo mới, tạo ra một  softlink  đến travellist trong sites-enabled :
- sudo ln -s /etc/nginx/sites-available/travellist /etc/nginx/sites-enabled/ 
 
Lưu ý: Nếu bạn có một  file   server  ảo mà trước đây đã được cấu hình cho cùng server_name sử dụng trong travellist  server  ảo, bạn có thể cần phải tắt cấu hình cũ bằng cách loại bỏ tương ứng bên trong  softlink  /etc/nginx/sites-enabled/ .
Để xác nhận cấu hình không có bất kỳ lỗi cú pháp nào, bạn có thể sử dụng:
- sudo nginx -t 
 
Bạn sẽ thấy kết quả như thế này:
Output- nginx: the configuration file /etc/nginx/nginx.conf syntax is ok 
 - nginx: configuration file /etc/nginx/nginx.conf test is successful 
 
Để áp dụng các thay đổi, hãy reload Nginx bằng:
- sudo systemctl reload nginx 
 
Nếu bạn reload trình duyệt của bạn ngay bây giờ, các hình ảnh ứng dụng sẽ bị hỏng. Điều đó xảy ra bởi vì ta đã di chuyển folder ứng dụng đến một vị trí mới bên trong server và vì lý do đó ta cần tạo lại softlink đến folder lưu trữ ứng dụng.
Xóa liên kết cũ với:
- cd /var/www/travellist 
 - rm -f public/storage 
 
Bây giờ hãy chạy lại    lệnh artisan để tạo liên kết lưu trữ:
- php artisan storage:link 
 
Bây giờ, hãy truy cập trình duyệt của bạn và truy cập ứng dụng bằng domain  hoặc địa chỉ IP của  server , như được xác định bởi chỉ thị server_name trong file  cấu hình của bạn:
http://server_domain_or_IP Trong bước tiếp theo, ta sẽ tích hợp một dịch vụ lưu trữ đối tượng vào ứng dụng. Điều này sẽ thay thế bộ nhớ đĩa local hiện tại được sử dụng cho ảnh du lịch.
Bước 5 - Tích hợp Bộ nhớ Đối tượng Tương thích S3 vào Ứng dụng
 Bây giờ  ta  sẽ  cài đặt  ứng dụng để sử dụng dịch vụ lưu trữ đối tượng tương thích với S3 để lưu trữ các bức ảnh du lịch được trưng bày trên trang index . Vì ứng dụng đã có một vài ảnh mẫu được lưu trữ trong đĩa local ,  ta  cũng sẽ sử dụng công cụ s3cmd để tải các file  ảnh local  hiện có lên bộ lưu trữ đối tượng từ xa.
Cài đặt trình điều khiển S3 cho Laravel
 Laravel sử dụng league/flysystem , một thư viện trừu tượng hệ thống file  cho phép ứng dụng Laravel sử dụng và kết hợp nhiều giải pháp lưu trữ, bao gồm đĩa local  và các dịch vụ  cloud . Cần có một gói bổ sung để sử dụng trình điều khiển s3 .  Ta  có thể cài đặt gói này bằng cách sử dụng lệnh composer require request.
Truy cập folder ứng dụng:
- cd /var/www/travellist 
 
- composer require league/flysystem-aws-s3-v3 
 
Bạn sẽ thấy kết quả tương tự như sau:
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 ... Bây giờ các gói bắt buộc đã được cài đặt,  ta  có thể cập nhật ứng dụng để kết nối với bộ lưu trữ đối tượng. Đầu tiên,  ta  sẽ mở lại file  .env để  cài đặt  chi tiết cấu hình như khóa, tên  group  và khu vực cho dịch vụ lưu trữ đối tượng của bạn.
 Mở file  .env :
- nano .env 
 
Bao gồm các biến môi trường sau, thay thế các giá trị được đánh dấu bằng chi tiết cấu hình object stores của bạn:
DO_SPACES_KEY=EXAMPLE7UQOTHDTF3GK4 DO_SPACES_SECRET=exampleb8e1ec97b97bff326955375c5 DO_SPACES_ENDPOINT=https://ams3.digitaloceanspaces.com DO_SPACES_REGION=ams3 DO_SPACES_BUCKET=sammy-travellist  Lưu file   khi bạn hoàn tất. Bây giờ hãy mở file  config/filesystems.php :
- nano config/filesystems.php 
 
Trong file  này,  ta  sẽ tạo một mục đĩa mới trong mảng disks .  Ta  sẽ đặt tên cho spaces đĩa này và  ta  sẽ sử dụng các biến môi trường mà  ta  đã đặt trong file  .env để  cấu hình  đĩa mới. Bao gồm mục nhập sau trong mảng 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'), ],  Vẫn trong cùng một file , hãy tìm mục nhập cloud và thay đổi nó để đặt đĩa spaces mới làm đĩa hệ thống file   cloud  mặc định:
'cloud' => env('FILESYSTEM_CLOUD', 'spaces'),  Lưu file   khi bạn chỉnh sửa xong. Từ bộ điều khiển của bạn, bây giờ bạn có thể sử dụng phương thức Storage::cloud() làm lối tắt để truy cập đĩa cloud mặc định. Bằng cách này, ứng dụng vẫn linh hoạt để sử dụng nhiều giải pháp lưu trữ và bạn có thể chuyển đổi giữa các nhà cung cấp trên cơ sở từng môi trường.
Ứng dụng hiện đã được cấu hình để sử dụng lưu trữ đối tượng, nhưng ta vẫn cần cập nhật mã tải ảnh mới lên ứng dụng.
 Đầu tiên  ta  hãy kiểm tra tuyến uploadPhoto hiện tại, nằm trong lớp PhotoController . Mở file  bằng editor  của bạn:
- 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'); }  Phương thức này chấp nhận yêu cầu POST và tạo mục nhập ảnh mới trong bảng ảnh. Quá trình này bắt đầu bằng cách kiểm tra xem một địa điểm hiện có đã được chọn trong biểu mẫu tải ảnh lên hay chưa và nếu không đúng như vậy, nó sẽ tạo một địa điểm mới bằng cách sử dụng thông tin được cung cấp. Địa điểm sau đó được đặt thành visited và lưu vào database . Sau đó, một liên kết được tạo để ảnh mới được liên kết với địa điểm được chỉ định. Các file ảnh sau đó được lưu trữ trong folder  root  của public đĩa. Cuối cùng, bức ảnh được lưu vào database . Sau đó  user  được chuyển hướng đến tuyến đường chính, là trang index  của ứng dụng.
 Dòng được đánh dấu trong mã này là những gì  ta  quan tâm. Trong dòng đó, file  hình ảnh được lưu vào đĩa bằng phương thức store . Phương thức store được sử dụng để lưu file  vào bất kỳ đĩa nào được xác định trong filesystem.php cấu hình filesystem.php . Trong trường hợp này, nó đang sử dụng đĩa mặc định để lưu trữ các hình ảnh đã tải lên.
  Ta  sẽ thay đổi hành vi này để hình ảnh được lưu vào repository  đối tượng thay vì đĩa local . Để làm được điều đó,  ta  cần phải thay thế các public đĩa bằng các spaces đĩa trong store gọi phương thức.  Ta  cũng cần  đảm bảo  mức độ hiển thị của file  đã tải lên được đặt thành công khai thay vì riêng tư .
 Đoạn mã sau chứa đầy đủ lớp PhotoController , bao gồm cả phương thức uploadPhoto được cập nhật:
<?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');    } }   Sao chép mã đã cập nhật vào PhotoController  của bạn  để nó phản ánh những thay đổi được đánh dấu.  Lưu file   khi bạn chỉnh sửa xong.
  Ta  vẫn cần sửa đổi chế độ xem chính của ứng dụng để nó sử dụng URL file  lưu trữ đối tượng để hiển thị hình ảnh. Mở mẫu travel_list.blade.php :
- nano resources/views/travel_list.blade.php 
 
Bây giờ xác định vị trí phần footer của trang, hiện có dạng như sau:
@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 Thay thế thuộc tính src hình ảnh hiện tại để sử dụng URL file  từ đĩa lưu trữ spaces :
<img src="{{ Storage::disk('spaces')->url($photo->image) }}" /> Nếu bạn truy cập trình duyệt của bạn ngay bây giờ và reload trang ứng dụng, nó sẽ chỉ hiển thị những hình ảnh bị hỏng. Điều đó xảy ra bởi vì các file hình ảnh cho những bức ảnh du lịch đó vẫn chỉ nằm trong đĩa local . Ta cần tải các file ảnh hiện có lên bộ lưu trữ đối tượng, để ảnh đã được lưu trữ trong database có thể được trưng bày thành công trong trang ứng dụng.
 Đồng bộ hóa hình ảnh local  với s3cmd
 Công cụ s3cmd  được dùng  để đồng bộ hóa các file  local  với dịch vụ lưu trữ đối tượng tương thích với S3.  Ta  sẽ chạy lệnh sync để tải tất cả các file  bên trong storage/app/public/photos lên dịch vụ lưu trữ đối tượng.
 Truy cập folder  lưu trữ ứng dụng public :
- cd /var/www/travellist/storage/app/public 
 
Để xem các file  đã được lưu trữ trong đĩa từ xa của bạn, bạn có thể sử dụng s3cmd ls :
- s3cmd ls s3://your_bucket_name 
 
Bây giờ hãy chạy lệnh sync để tải các file  hiện có trong folder  lưu trữ công cộng lên bộ lưu trữ đối tượng:
- s3cmd sync ./ s3://your_bucket_name --acl-public --exclude=.gitignore 
 
Thao tác này sẽ đồng bộ hóa folder  hiện tại ( storage/app/public ) với dir root  của bộ lưu trữ đối tượng từ xa. Bạn sẽ nhận được  kết quả  tương tự như sau:
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. Bây giờ, nếu bạn chạy lại s3cmd ls , bạn sẽ thấy rằng ba file  mới đã được thêm vào folder  root  của  group  lưu trữ đối tượng của bạn:
- 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 Truy cập trình duyệt của bạn và reload trang ứng dụng. Tất cả các hình ảnh sẽ hiển thị ngay bây giờ và nếu bạn kiểm tra chúng bằng công cụ gỡ lỗi của trình duyệt, bạn sẽ nhận thấy rằng tất cả chúng đều sử dụng URL từ bộ nhớ đối tượng của bạn.
Kiểm tra sự tích hợp
Ứng dụng demo hiện có đầy đủ chức năng, lưu trữ file trong dịch vụ lưu trữ đối tượng từ xa và lưu dữ liệu vào database MySQL được quản lý. Bây giờ ta có thể tải lên một vài ảnh để kiểm tra cài đặt của bạn .
 Truy cập tuyến /upload ứng dụng từ trình duyệt của bạn:
http://server_domain_or_IP/upload Bạn sẽ thấy biểu mẫu sau:
Đến đây bạn có thể tải lên một vài ảnh để kiểm tra việc tích hợp bộ nhớ đối tượng. Sau khi chọn hình ảnh từ máy tính, bạn có thể chọn một địa điểm hiện có từ menu thả xuống hoặc bạn có thể thêm một địa điểm mới bằng cách cung cấp tên và tọa độ địa lý của nó để có thể tải nó vào bản đồ ứng dụng.
Bước 6 - Mở rộng quy mô database MySQL được quản lý DigitalOcean với các node chỉ đọc (Tùy chọn)
 Bởi vì các hoạt động chỉ đọc thường thường xuyên hơn các hoạt động ghi trên  server  database , một thực tế phổ biến là mở rộng một cụm database  bằng cách  cài đặt  nhiều nút chỉ đọc. Điều này sẽ phân phối tải được tạo ra bởi các hoạt động SELECT .
Để chứng minh cài đặt này, trước tiên ta sẽ thêm 2 nút chỉ đọc vào cụm DigitalOcean Managed MySQL của ta . Sau đó, ta sẽ cấu hình ứng dụng Laravel để sử dụng các node này.
Truy cập Control panel cloud DigitalOcean và làm theo các hướng dẫn sau:
- Đi tới Database và chọn cụm MySQL của bạn.
 -  Nhấp vào 
Actionsvà chọnAdd a read-only nodetừ trình đơn thả xuống. - Cấu hình các tùy chọn nút và nhấn nút Tạo . Lưu ý có thể mất vài phút để nút mới sẵn sàng.
 - Lặp lại các bước 1-4 để bạn có 2 nút chỉ đọc.
 - Ghi lại các server của hai nút vì ta cần chúng cho cấu hình Laravel của bạn .
 
Khi bạn đã chuẩn bị xong các node chỉ đọc, hãy quay lại terminal của bạn.
 Bây giờ  ta  sẽ cấu hình ứng dụng Laravel  của bạn  để hoạt động với nhiều nút database . Khi  ta  hoàn tất, các truy vấn như INSERT và UPDATE sẽ được chuyển tiếp đến nút cụm chính của bạn, trong khi tất cả các truy vấn SELECT sẽ được chuyển hướng đến  các node  chỉ đọc của bạn.
 Trước tiên, hãy chuyển đến folder  của ứng dụng trên  server  và mở file  .env của bạn bằng editor  mà bạn chọn:
- cd /var/www/travellist 
 - nano .env 
 
Tìm cấu hình database  MySQL và  comment  dòng 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  Lưu file   khi bạn hoàn tất. Bây giờ mở config/database.php trong editor  của bạn:
- nano config/database.php 
 
Tìm mục nhập mysql bên trong mảng connections . Bạn nên bao gồm ba mục mới trong mảng cấu hình này: read , write và sticky . Các read và write các mục sẽ  cài đặt   các node  cluster, và sticky tùy chọn  cài đặt  để true sẽ tái sử dụng write các kết nối để các dữ liệu ghi vào database  có sẵn ngay trong chu kỳ yêu cầu tương tự. Bạn có thể đặt nó thành false nếu bạn không muốn hành vi này.
...       'mysql' => [          'read' => [            'host' => [               'READONLY_NODE1_HOST',               'READONLY_NODE2_HOST',            ],          ],          'write' => [            'host' => [              'MANAGED_MYSQL_HOST',            ],          ],        'sticky' => true, ...  Lưu file   khi bạn chỉnh sửa xong. Để kiểm tra xem mọi thứ có hoạt động như mong đợi hay không,  ta  có thể tạo một đường dẫn tạm thời bên trong routes/web.php để lấy một số dữ liệu từ database  và hiển thị chi tiết về kết nối đang được sử dụng. Bằng cách này,  ta  sẽ có thể xem các yêu cầu đang được cân bằng tải như thế nào giữa  các node  chỉ đọc.
 Mở file  tin routes/web.php :
- nano routes/web.php 
 
Bao gồm các tuyến đường sau:
...  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; }); Bây giờ, hãy truy cập trình duyệt của bạn và truy cập vào tuyến ứng dụng /mysql-test :
http://server_domain_or_IP/mysql-test Bạn sẽ thấy một trang như thế này:
  Reload  trang một vài lần và bạn sẽ nhận thấy rằng giá trị Server ID thay đổi, cho biết rằng các yêu cầu đang được phân phối ngẫu nhiên giữa hai nút chỉ đọc.
Kết luận
Trong hướng dẫn này, ta đã chuẩn bị một ứng dụng Laravel 6 cho một môi trường có khả năng mở rộng và khả dụng cao. Ta đã thuê ngoài hệ thống database cho một dịch vụ MySQL được quản lý bên ngoài và ta đã tích hợp dịch vụ lưu trữ đối tượng tương thích với S3 vào ứng dụng để lưu trữ các file do user tải lên. Cuối cùng, ta đã thấy cách mở rộng database của ứng dụng bằng cách bao gồm các node cụm chỉ đọc bổ sung trong file cấu hình của ứng dụng.
Bạn có thể tìm thấy mã ứng dụng demo được cập nhật chứa tất cả các sửa đổi được thực hiện trong hướng dẫn này trong thẻ 2.1 trong repository ứng dụng trên Github.
Từ đây, bạn có thể cài đặt Load Balancer để phân phối tải và chia tỷ lệ ứng dụng của bạn giữa nhiều nút. Bạn cũng có thể tận dụng cài đặt này để tạo một môi trường chứa để chạy ứng dụng của bạn trên Docker.
Các tin liên quan

