Laravel 11: Ứng dụng thời gian thực Websocket với Laravel Reverb

Cập nhật vào

Mục luc:

Laravel 11: Ứng dụng thời gian thực Websocket với Laravel Reverb

Giới thiệu

Laravel Reverb mang đến khả năng giao tiếp WebSocket thời gian thực nhanh chóng và mở rộng được trực tiếp vào ứng dụng Laravel của bạn, cùng với tích hợp hoàn hảo với bộ công cụ phát sóng sự kiện (broadcasting) hiện có của Laravel.

Cách cài đặt Laravel Reverb

Bạn có thể cài đặt Reverb bằng cách sử dụng lệnh Artisan install:broadcasting, tưởng tượng giống cách bạn cài đặt API vào ứng dụng Laravel của bạn.

1php artisan install:broadcasting

Cấu hình config Laravel Reverb

Bên trong, lệnh Artisan install:broadcasting sẽ chạy lệnh reverb:install, từ đó sẽ cài đặt Reverb với một tập hợp các tùy chọn cấu hình mặc định hợp lý. Nếu bạn muốn thay đổi cấu hình, bạn có thể làm điều đó bằng cách cập nhật các biến môi trường của Reverb hoặc cập nhật tệp cấu hình config/reverb.php.

Cấu hình biến môi trường

Để thiết lập kết nối với Reverb, một bộ thông tin đăng nhập “ứng dụng” Reverb phải được trao đổi giữa client và server. Những thông tin đăng nhập này được cấu hình trên server và được sử dụng để xác minh yêu cầu từ phía client. Bạn có thể xác định thông tin đăng nhập này bằng cách sử dụng các biến môi trường sau:

1REVERB_APP_ID=my-app-id
2REVERB_APP_KEY=my-app-key
3REVERB_APP_SECRET=my-app-secret

Cho phép clients truy cập vào Websockets server Laravel Reverb (origin)

Bạn cũng có thể cho phép clients truy cập vào Websocket server của Laravel Reverb bằng cách cập nhật giá trị của cấu hình allowed_origins trong phần apps của tệp cấu hình config/reverb.php. Mọi yêu cầu từ một origin không được liệt kê trong danh sách origin được phép sẽ bị từ chối. Bạn có thể cho phép tất cả các origin bằng cách sử dụng ký tự *:

1'apps' => [
2 [
3 'id' => 'my-app-id',
4 'allowed_origins' => ['laravel.com'],
5 // ...
6 ]
7]

Triển khai với nhiều ứng dụng cùng một lúc

Thường thì, Reverb cung cấp một máy chủ WebSocket cho ứng dụng mà nó được cài đặt. Tuy nhiên, bạn có thể phục vụ nhiều hơn một ứng dụng bằng cách sử dụng một cài đặt Reverb duy nhất.

Ví dụ, bạn có thể muốn duy trì một ứng dụng Laravel duy nhất mà thông qua Reverb, cung cấp khả năng kết nối WebSocket cho nhiều ứng dụng. Điều này có thể được thực hiện bằng cách xác định nhiều ứng dụng trong tệp cấu hình config/reverb.php của ứng dụng của bạn:

1'apps' => [
2 [
3 'id' => 'my-app-one',
4 // ...
5 ],
6 [
7 'id' => 'my-app-two',
8 // ...
9 ],
10],

Bảo mật với SSL

Trong hầu hết các trường hợp, các kết nối WebSocket an toàn được xử lý bởi máy chủ web (Nginx, vv.) trước khi yêu cầu được proxy đến máy chủ Reverb của bạn.

Tuy nhiên, đôi khi nó có thể hữu ích, như trong quá trình phát triển cục bộ, để máy chủ Reverb xử lý các kết nối an toàn trực tiếp. Nếu bạn đang sử dụng tính năng bảo mật web của Laravel Herd hoặc bạn đang sử dụng Laravel Valet và đã chạy lệnh secure cho ứng dụng của bạn, bạn có thể sử dụng chứng chỉ Herd/Valet được tạo ra cho trang web của bạn để bảo mật các kết nối Reverb của bạn. Để làm điều này, hãy đặt biến môi trường REVERB_HOST thành tên máy chủ của trang web của bạn hoặc truyền tường minh tùy chọn hostname khi khởi động máy chủ Reverb:

1php artisan reverb:start --host="0.0.0.0" --port=8080 --hostname="laravel.test"

Vì các miền Herd và Valet đượcchuyển thành localhost, chạy lệnh trên sẽ cho phép truy cập vào máy chủ Reverb của bạn thông qua giao thức WebSocket an toàn (wss) tại wss://laravel.test:8080.

Bạn cũng có thể chọn chứng chỉ một cách thủ công bằng cách xác định tùy chọn tls trong tệp cấu hình config/reverb.php của ứng dụng của bạn. Trong mảng các tùy chọn tls, bạn có thể cung cấp bất kỳ tùy chọn nào được hỗ trợ bởi các tùy chọn ngữ cảnh SSL của PHP:

1'options' => [
2 'tls' => [
3 'local_cert' => '/path/to/cert.pem'
4 ],
5],

Khởi chạy máy chủ Laravel Reverb

Máy chủ Reverb có thể được khởi động bằng lệnh Artisan reverb:start

1php artisan reverb:start

Mặc định, máy chủ Reverb sẽ được khởi động tại 0.0.0.0:8080, cho phép truy cập từ tất cả các giao diện mạng.

Nếu bạn cần chỉ định một máy chủ hoặc cổng tùy chỉnh, bạn có thể làm như vậy thông qua các tùy chọn --host--port khi khởi động máy chủ:

1php artisan reverb:start --host=127.0.0.1 --port=9000

Hoặc, bạn có thể xác định các biến môi trường REVERB_SERVER_HOSTREVERB_SERVER_PORT trong tệp cấu hình .env của ứng dụng của bạn.

Gỡ lỗi khi Laravel Reverb gặp sự cố

Để cải thiện hiệu suất, mặc định Reverb không hiển thị bất kỳ thông tin gỡ lỗi nào. Nếu bạn muốn xem dữ liệu truyền qua máy chủ Reverb của bạn, bạn có thể sử dụng tùy chọn --debug khi chạy lệnh reverb:start:

1php artisan reverb:start --debug

Khởi động lại Laravel Reverb

Vì Reverb là một tiến trình chạy lâu dài (long-running process), các thay đổi trong mã của bạn sẽ không được cập nhật ngay mà không cần khởi động lại máy chủ thông qua lệnh reverb:restart của Artisan.

Lệnh reverb:restart đảm bảo tất cả các kết nối được kết thúc một cách toàn vẹn (gracefully terminated) trước khi dừng máy chủ. Nếu bạn đang chạy Reverb với một quản lý quy trình như Supervisor, máy chủ sẽ được tự động khởi động lại bởi quản lý quy trình sau khi tất cả các kết nối đã được chấm dứt:

1php artisan reverb:restart

Chạy Laravel Reverb trên môi trường production

Do tính chất chạy lâu dài của máy chủ WebSocket, bạn có thể cần thực hiện một số tối ưu hóa cho máy chủ và môi trường lưu trữ của bạn để đảm bảo máy chủ Reverb của bạn có thể xử lý hiệu quả số lượng kết nối tối ưu cho tài nguyên có sẵn trên máy chủ của bạn.

Cấu hình số lượng tập tin tối đa cùng mở tại một thời điểm

Mỗi kết nối WebSocket được lưu giữ trong bộ nhớ cho đến khi client hoặc server ngắt kết nối. Trong môi trường Unix và tương tự, mỗi kết nối được đại diện bởi một tập tin. Tuy nhiên, thường có giới hạn về số lượng tập tin mở được cho phép cả ở mức hệ điều hành và ứng dụng.

Cấu hình ở hệ điều hành

Trên hệ điều hành dựa trên Unix, bạn có thể xác định số lượng tệp mở được phép bằng lệnh ulimit:

1ulimit -n

Lệnh này sẽ hiển thị giới hạn tệp mở được phép cho các người dùng khác nhau. Bạn có thể cập nhật các giá trị này bằng cách chỉnh sửa tệp /etc/security/limits.conf. Ví dụ, cập nhật số lượng tệp mở tối đa thành 10.000 cho người dùng forge sẽ như sau:

1/etc/security/limits.conf
2forge soft nofile 10000
3forge hard nofile 10000

Cấu hình vòng lặp sự kiện (Event Loop)

Ở phía dưới, Reverb sử dụng một vòng lặp sự kiện (Event Loop) của ReactPHP để quản lý kết nối WebSocket trên máy chủ. Cơ chế của nó tương tự như NodeJS nhưng hoàn toàn là PHP nên bạn có thể yên tâm sử dụng vì nó không phải là một WebSocket lai tạp bằng cách sử dụng các trick lỏ như long-polling hay NodeJS wrapper.

Mặc định, vòng lặp sự kiện này được cung cấp bởi stream_select, không yêu cầu bất kỳ tiện ích bổ sung nào. Tuy nhiên, stream_select thường bị giới hạn đến 1.024 tệp mở. Do đó, nếu bạn dự định xử lý hơn 1.000 kết nối đồng thời, bạn sẽ cần sử dụng một vòng lặp sự kiện thay thế không bị ràng buộc bởi các giới hạn tương tự.

Reverb sẽ tự động chuyển sang một vòng lặp sự kiện được kích hoạt bởi ext-event, ext-ev, hoặc ext-uv khi có sẵn. Tất cả các tiện ích PHP này có thể được cài đặt thông qua PECL:

1pecl install event

hoặc

1pecl install ev

hoặc

1pecl install uv

Cấu hình máy chủ web

Trong hầu hết các trường hợp, Reverb chạy trên một cổng không phải là cổng truy cập web trên máy chủ của bạn. Vì vậy, để định tuyến lưu lượng truy cập đến Reverb, bạn nên cấu hình một reverse proxy. Giả sử Reverb đang chạy trên máy chủ 0.0.0.0 và cổng 8080 và máy chủ của bạn sử dụng máy chủ web Nginx, một reverse proxy có thể được xác định cho máy chủ Reverb của bạn bằng cấu hình trang Nginx sau đây:

1server {
2 ...
3 
4 location / {
5 proxy_http_version 1.1;
6 proxy_set_header Host $http_host;
7 proxy_set_header Scheme $scheme;
8 proxy_set_header SERVER_PORT $server_port;
9 proxy_set_header REMOTE_ADDR $remote_addr;
10 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
11 proxy_set_header Upgrade $http_upgrade;
12 proxy_set_header Connection "Upgrade";
13 
14 proxy_pass http://0.0.0.0:8080;
15 }
16 
17 ...
18}

Thường, các máy chủ web được cấu hình để giới hạn số lượng kết nối được phép để tránh quá tải máy chủ. Để tăng số lượng kết nối được phép trên máy chủ web Nginx lên 10.000, các giá trị worker_rlimit_nofileworker_connections trong tệp nginx.conf nên được cập nhật:

1user forge;
2worker_processes auto;
3pid /run/nginx.pid;
4include /etc/nginx/modules-enabled/*.conf;
5worker_rlimit_nofile 10000;
6
7events {
8 worker_connections 10000;
9 multi_accept on;
10}

Cấu hình trên sẽ cho phép tạo ra tối đa 10.000 tiến trình Nginx trên mỗi quá trình. Ngoài ra, cấu hình này đặt giới hạn tệp mở của Nginx thành 10.000.

Cấu hình cổng truy cập

Các hệ điều hành dựa trên Unix thường giới hạn số lượng cổng mà có thể mở trên máy chủ. Bạn có thể xem phạm vi cổng hiện được phép thông qua lệnh sau:

1cat /proc/sys/net/ipv4/ip_local_port_range
2# 32768 60999

Đầu ra kết quả cho thấy máy chủ có thể xử lý tối đa 28.231 (60.999 - 32.768) kết nối vì mỗi kết nối đòi hỏi một cổng trống. Mặc dù chúng tôi khuyến nghị mở rộng theo chiều ngang để tăng số lượng kết nối được phép, bạn có thể tăng số lượng cổng mở có sẵn bằng cách cập nhật phạm vi cổng được phép trong tệp cấu hình /etc/sysctl.conf của máy chủ của bạn.

Cấu hình quản lý tiến trình

Trong hầu hết các trường hợp, bạn nên sử dụng một quản lý quy trình như Supervisor để đảm bảo máy chủ Reverb luôn chạy. Nếu bạn đang sử dụng Supervisor để chạy Reverb, bạn nên cập nhật cài đặt minfds trong tệp supervisor.conf của máy chủ để đảm bảo Supervisor có thể mở các tệp cần thiết để xử lý kết nối đến máy chủ Reverb của bạn:

1[supervisord]
2...
3minfds=10000

Cảm ơn các bạn đã dành thời gian đọc bài!

Recommended