Cài đặt server websockets trên AWS EC2 với Laravel WebSockets
Bạn là người chơi hệ PHP nhưng lại muốn realtime thì đây là bài viết dành cho bạn. Trước khi vào bài viết thì các bạn cần biết websockets. Mình đã dựng lên con websockets này trong hoàn cảnh:
- Khách hàng muốn làm 1 ứng dụng chat realtime nhưng lại lại không cho dùng Pusher vì phí khá đắt.
- Firebase Cloud Messaging thì ổn nhưng lại bị dính đến quyền browser (nếu không bật notice ở browser thì không chat được).
- Socket I.O là giải pháp hay nhưng mình nói từ đầu rồi đấy "do là người chơi hệ PHP".
Nói chung cuộc sống éo le đưa mình tới websockets nhưng sau khi cài xong thì thấy "ok" cũng ko tệ :)).
Để cài đặt ta việc ta cần làm:
Bước 1. Dựng con instance EC2, có source code để keep 1 con websockets đảm nhiệm connect tới tất cả client.
Bước 2. Nếu ứng dụng của bạn dùng HTTPS thì bạn phải cài TLS cho websocket ở đây mình dùng ALB của AWS để tạo.
Bước 3. Cần 1 subdomain để connect đến ALB ở đây mình dùng Route 53 để tạo rồi connect với ALB.
Ở đây mình con như bạn đã có 1 con server web hoàn chỉnh chỉ còn cần cài websocket nữa thôi. Chúng ta sẽ đi vào từng bước:
Bước 1: Cài đặt trên EC2
Cài đặt package
composer require beyondcode/laravel-websockets
Gói sẽ tự động đăng ký nhà cung cấp dịch vụ.
Gói này đi kèm với một sự di chuyển để lưu trữ thông tin thống kê trong khi chạy máy chủ WebSocket của bạn. Bạn có thể xuất bản tệp di chuyển bằng cách sử dụng:
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
chạy migrate:
php artisan migrate
Tiếp theo, bạn cần xuất bản tệp cấu hình WebSocket:
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"
Cài đặt Pusher ( ở đây chúng ta vẫn dùng config như Pusher chỉ là không connect đến server của Pusher thôi nhé :D)
composer require pusher/pusher-php-server
trong file .env thêm những phần mà config trong pusher bạn có thể điền gì vào đó cũng được sau này chỉ có PUSHER_APP_KEY là sẽ cần khớp phần cài đặt phía client để hứng event thôi.
PUSHER_APP_ID=<id tự định nghĩa là 1 string>
PUSHER_APP_KEY=<KEY tự định nghĩa là 1 string>
PUSHER_APP_SECRET=<SECRET tự định nghĩa là 1 string>
PUSHER_APP_CLUSTER=<CLUSTER tự định nghĩa là 1 string>
BROADCAST_DRIVER=pusher
PUSHER_SCHEMA=https
PUSHER_USE_TLS=true
PUSHER_HOST='subdomain tạo ở bước 3'
trong config/broadcasting.php ta config
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => env('PUSHER_USE_TLS', 'false'),
'encrypted' => env('PUSHER_ENCRYPTED', 'true'),
'host' => env('PUSHER_HOST', '127.0.0.1'),
'port' => env('PUSHER_PORT', '6001'),
'scheme' => env('PUSHER_SCHEMA', 'http'),
],
],
Để nhận và gửi gói tin qua cổng 6001
php artisan websockets:serve --port=6001
Theo mặc định, máy chủ Laravel WebSocket sẽ lắng nghe 0.0.0.0
và cho phép các kết nối đến từ tất cả các mạng. Nếu bạn muốn hạn chế điều này, bạn có thể khởi động máy chủ bằng một --host
tùy chọn, sau đó là IP.
Ví dụ: bằng cách sử dụng 127.0.0.1
, bạn sẽ chỉ cho phép các kết nối WebSocket từ localhost.
Để keep proccess này ta nên dùng supervisor để đảm bảo nó luôn luôn chạy:
Sau khi cài đặt supervisor , hãy thêm một quy trình mới supervisor
cần tiếp tục chạy. Bạn đặt cấu hình của mình trong thư mục /etc/supervisor/conf.d
(Debian / Ubuntu) hoặc /etc/supervisord.d
(Red Hat / CentOS).
Trong thư mục đó, hãy tạo một tệp mới có tên websockets.conf
.
[program:websockets]
command=/usr/bin/php /home/laravel-websockets/artisan websockets:serve
numprocs=1
autostart=true
autorestart=true
user=ubuntu
Sau khi được tạo, hãy hướng dẫn supervisor
tải lại các tệp cấu hình của nó (mà không ảnh hưởng đến các supervisor
công việc đang chạy).
supervisorctl update
supervisorctl start websockets
Phía server cần mở port cho cổng 6001 trên cả (aws) network sercurity group
và trong iptables
sudo ufw allow 6001
Bước 2: Cài TLS với ALB
Tạo 1 target group trỏ đến instance ec2 qua port 6001
Enabled Stickiness trong tab Attributes
Tạo 1 network load balancer và trỏ vào target group qua cổng 6001 nhớ phải add certificates cho nó nhé các bạn.
Bước 3: Trong route 53 tạo 1 subdomain trỏ đến ALB
Vậy là đã setup xong 1 con server websockets
Để hứng được event bên client bạn sẽ cần dùng Laravel Echo
VD: nếu dùng VueJs
import Echo from "laravel-echo"
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key', // chính là PUSHER_APP_KEY trong .env
wsHost: window.location.hostname, // là subdomain bạn tạo ra
wsPort: 6001,
wssPort: 6001,
forceTLS: true, // nếu là wss
disableStats: true,
});
Hy vọng bài viết có ích cho các bạn :D bye bye :))