[ask] webpush notification - Gửi đến nhiều người dùng cùng lúc
Đây là lần thứ 2 mình hỏi lại về vấn đề này, Lần trước là Subscription gồm mảng 600 phần tử khi chạy hàm foreach
nên mình chuyển về mảng nhỏ hơn 500.
Vân đề là giờ code chạy chậm và đến 2000 là bị lỗi đứng + CPU chạy >90%.
Nên mình muốn nhờ một bạn làm về PHP xem cũng như tư vấn để tối ưu hơn cho mình, Sẽ gửi phí ạ, mình không rành code lắm
Tóm lược:
- Mình đang có database ~ 20K row định dạng
fcm.googleapis.com
=> Mình gửi bằng https://github.com/web-push-libs/web-push-php
Đây là cách mình đã làm: Gửi ALL
- Đưa danh sách gửi vào database
notifications_schedule
với 3 tham số chính là:endpoint_start
endpoint_end
status
- function
get_schedule_notification
Lấy tin nhắn cần gửi cóstatus
chưa gửi. - function
set_schedule_notification
kiểm tra nếu$endpoint_start >= $endpoint_end
thì cập nhậtstatus
hoàn thành. Không sẽ chạy Hàm chính - function
get_schedule_endpoint_list
lấy danh sách người dùng theoendpoint_start
endpoint_end
- function
send_notifications
gửi notification theo danh sách đã lấy trên.
Hàm chính: get_schedule_notification
=> get_schedule_endpoint_list
=> send_notifications
=> set_schedule_notification
.
Trên là tuần tự code mình đã làm.
Đây là file code để đọc rõ ràng hơn: ( xin lỗi vì cách viết tệ của mình): https://gist.github.com/bcat95/4236f6d81d3cbddb12fd8c65166330e5
3 ANSWERS
code trên bạn chạy theo request base hay chạy trong worker, nếu chưa chạy trong woker hãy đưa vào worker. Hãy sử dụng queue jobs để giải quyết vấn đề này, bạn hãy implenment laravel queue https://github.com/illuminate/queue :
- tạo một job để push jobs vào queue, tên là InitNotifications chẳng hạn. job này sẽ lấy dữ liệu trong database của bạn, như giờ là khoảng 20k, và push job 20k job tương ứng với 20k row dữ liệu này vào queue của bạn. Khi có request thực hiện chức năng này, job sẽ được thực hiện trong worker thay vì process của request hiện tại. Bạn chỉ cần push job này vào queue và trả về status ok. Vì dữ liệu nhiều hãy dùng queue redis, chúng ta sẽ cần dùng nhiều process worker nên redis sẽ tốt hơn rdsdb
- tạo 1 job thực hiện việc push notification, tên là PushNotification chẳng hạn, job này chính là job bạn cần push vào queue như đã nói ở trên.
- hãy dùng supervisor để handle các woker, tùy resource của bạn hãy set numproc hợp lý.
- hãy tạo 2 queue, 1 queue để push InitNotifications job, và 1 queue để push PushNotification job.
bonus:
- bạn nên dùng socket để thông báo trên trang hiển thị là job đã làm đến bước nào, ví dụ khi push hết jobs vào queue hãy thông báo, khi jobs trong queue được thực hiện hết hãy thông báo.
- bạn cũng nên tạo 1 table trong rdsdb để chứa các jobs lỗi, và bạn cũng có thể viết thêm script get jobs từ đây để chạy lại.
Cảm ơn, phức tạp thật. Mình đọc làm theo các bước xem. Đầu tiên tìm hiểu Laravel => Laravel Queue
@Stevendie ko muốn làm thì thuê mình làm cho
Mình có sử dụng $sendList = array_chunk($arr_endpoint_id, 100, true);
thì cũng chạy đến tầm 2000 là bị. Nên thử queue nghĩ sẽ tối ưu hơn.
@Stevendie Xin lỗi mình đọc k kĩ, nhưng mà có vẻ query hiện tại của bạn k có gì phức tạp đến mức cần tối ưu. Bạn thử dùng thêm queue xem (như support của bạn Trung)
Mình làm bên C# có SignalR bên php mình tìm có thầy WebSockets. https://stackoverflow.com/questions/35473356/is-there-any-javascript-tcp-soket-library-for-php-like-signalr-with-net Việc dùng gửi dến từng người 1 sẽ rất tốn tài nguyên và ko realtime. Nên dù bạn tối ưu đến đâu cũng sẽ đều có ngưỡng mà tốn tài nguyên sever để send rất nhiều.