Asked Feb 11th, 2020 7:33 a.m. 323 0 3
  • 323 0 3
+3

[ask] webpush notification - Gửi đến nhiều người dùng cùng lúc

Share
  • 323 0 3

Đâ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ật status 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 theo endpoint_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


Answered Feb 11th, 2020 10:15 a.m.
+2

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.
Share
Avatar Trúc Mai @Stevendie
Feb 11th, 2020 1:30 p.m.

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

0
| Reply
Share
Feb 12th, 2020 4:06 a.m.

@Stevendie ko muốn làm thì thuê mình làm cho

0
| Reply
Share
Avatar Trúc Mai @Stevendie
Feb 13th, 2020 1:41 a.m.
Answered Feb 12th, 2020 1:22 a.m.
0

Bạn tìm hiểu thử hàm chunk() xem. Thay vì dùng foreach(), bạn nên dùng chunk(), việc chia nhỏ và chạy từng phần một sẽ giúp hệ thống đỡ bị quá tải.

Ví dụ một chút:

$sendList->chunk(100, function($users) {
    // Code send notifications to $users
});
Share
Avatar Trúc Mai @Stevendie
Feb 12th, 2020 1:38 a.m.

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.

0
| Reply
Share
Avatar Hải Hà @HaiHaChan
Feb 12th, 2020 1:45 a.m.

@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)

0
| Reply
Share
Answered Feb 18th, 2020 4:48 a.m.
0

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.

Share
Viblo
Let's register a Viblo Account to get more interesting posts.