سلام
یه بخشی از نرم افزار می خوام به صورت مدام و بر اساس زمان های خاص یکسری پیام به کاربران ارسال کنم. (پیامک،ایمیل و تلگرام).
پیامک رو مشکلی ندارم چون محدودیت زیادی ندارم.
اما برای تلگرام محدودیت 30 پیام در ثانیه وجود داره و برای ایمیل هم محدویت دارم ولی نه مثل تلگرام بر اساس ثانیه.
مشکل اصلیم اینه چطور کاری کنم وقتی می خوام به 30000 هزار کاربر پیام بدم در کمترین زمان اینکار رو انجام بدم. این محدودیت یعنی اینکه من می تونم در یک دقیقه به 1800 نفر در بهترین حالت پیام ارسال کنم که برای 30000 کاربر میشه 17 دقیقه. ولی در عمل باید کاربران رو مثلا به گروه های 29 یا 28 (برای اطمینان بیشتر)تقسیم کنم و بین هر گروه 1 ثانیه تاخیر بزارم و هر گروه 500 میلی ثانیه طول بکشه در مجموع 25 دقیقه زمان میبره.
سوالم اینه چطور زمان رو مدیریت کنم که بر اساس همون 1 ثانیه بشه و پرتی زمان کمتر بشه؟ یعنی اگر زمان ارسال یک گروه 30تایی پیام شد 100 میلی ثانیه من 900 میلی ثانیه delay بزارم.
یه راه ساده که خودم به ذهنم می رسه این دو روشی که گذاشتم که زمان و یا تعداد پیام رو چک کنم
**** با دو حلقه****
foreach (array_chunk($data, 29) as $chunkData)
{
$time_start = microtime(true);
foreach ($chunkData as $message)
{
$telegram->sendMessage($message, $id);
$numberMessage++;
}
$time_end = microtime(true);
if (($time_end - $time_start) < 1100000)
{
usleep(1100000 - ($time_end - $time_start));
}
}
****روش دوم با یک حلقه****
$numberMessage = 0;
$time_start = microtime(true);
foreach ($data as $message)
{
$telegram->sendMessage($message, $id);
$numberMessage++;
if ($numberMessage == 29)
{
$time_end = microtime(true);
if (($time_end - $time_start) < 1100000)
{
usleep(1100000 - ($time_end - $time_start));
$time_start = microtime(true);
$numberMessage = 0;
}
}
}
سلام
وقتی با انبوهی از پیام ها وجود داشته باشه راه مناسبش استفاده از امکاناتی همچون queue هست. یا حتی اگر نخواهید از queue استفاده کنید بهتره یه تیبل مخصوص پیام ها داشته باشید که برای هر کاربر و پیام مربوطه یک ردیف داشته باشه و پس از هر ارسال موفق اون پیام از گردونه ارسال حذف بشه یعنی به نحوی صف رو خودتون ایجاد کنید حالا برای مدیریت ارسال هم کرون جاب روش مناسبی است اما محدود کردن زمان ارسال با دقت میکرو ثانیه در عمل ممکنه نتیجه دلخواه رو رقم نزنه چون همیشه موارد بازگشتی تحت کنترل سیستم ارسال نیستند و تاخیر ایجاد شده برنامه ریزی رو مختل میکنه.
قطعا برای این کار در لاراول باید از queue استفاده کنید.
و در اجرای صف از rate limiter خود لاوال استفاده کنید
https://laravel.com/docs/8.x/queues#rate-limiting
ضمنا این پکیج هم چند سال پیش معرفی شده که همین کار رو میکنه
ممنون بابت پاسخ ها
چون این ارسال پیام یه سری داده است که ایجاد میشن و هر سی دقیقه یک بار یه job اجرا میشه و نتایج این job به کاربران ارسال میشه حالا اگه این زمان بیشتر از 30 دقیقه بشه کاربرانی که انتهای پردازش قرار می گیرند عملا داده ها رو خیلی دیر دریافت می کنن به طوری که قابل استفاده نیستند چون داده جدید تولید شده و داده 30 دقیقه قبل کارایی نداره. برای همین زمان برای من خیلی مهم هست و از طرفی تلگرام در یک ثانیه بیشتر از 30 پیام رو نمی زاره ارسال بشه.
به نظرم هزینه زمانی اجرای صف خیلی زیاد میشه
اگر صف رو ایجاد نکنید و response ها رو برای تایید ارسال موفقیت آمیز پردازش نکنید ممکنه تعداد قابل توجهی ارسال ناموفق داشته باشید که از اونها اطلاع پیدا نکنید و اگر پردازش response ها رو به حلقه واگذار کنید عملا زمان زیادی برای ارسال و توقف های برنامه ریزی نشده از دست خواهید داد.
بخش اول تولید پیام روی سرور شما اجرا میشه پس بدون نگرانی از زمان می تونید صرفا با توجه به حجم کوئری و در نظر گرفتن تایم اوت اون ها رو تولید کنید و فاصله زمانی کرون جاب رو کاهش بدید اما ارسال ها که متاثر از response هم هستند رو به کرون جاب واگذار کنید. در این موارد بهتره به جای کرون جاب سی پنل از سیستم های تجاری کرون جاب استفاده کنید. از setcronjob استفاده کردم، خوبه.
برای محدودیت ارسال هم می تونید از چند اکانت برای ارسال استفاده کنید تا موضوع محدودیت ارسال به شکل بهتری روی چند منبع توزیع بشه.
@majid4073
جالبه، درست میگید اگر پیام ها در یک بازه زمانی کوتاه معتبر باشن با شیوه ای که گفتم ممکنه در تعداد زیاد پیام ها خیلی دیر به دست مخاطب برسه.
در این حالت فقط راه حل این میتونه باشه که محدودیت 30 پیام در ثانیه وجود نداشته باشه که خب نمیشه ، مستندات تلگرام رو هم دیدم به نظر راهی پیشنهاد نداده
در این حالت تنها راهی که به نظر میرسه ارسال در گروه هست، اگر کاربران پیام های یکسان دریافت میکنن، همه رو در یک گروه خصوص اد کنید و ربات شما فقط بصورت دوره ای چک کنه که کاربری که نباید در گروه نباشه و اگر اعتبارش تموم شد از گروه حذف بشه، پیام هم فقط برای همون گروه ارسال بشه، حالا 1 میلیون نفر هم تو گروه باشن همزمان پیام رو دریافت میکنن
آیا مایل به ارسال نوتیفیکیشن و اخبار از طرف راکت هستید ؟