یه پلتفرم مثل شبکه های اجتماعی رو در نظر بگیرید ، اگر چندین نفر مدام یه فرم - مثلا ویرایش پروفایل - با شرط زیر سابمیت کنن ، بار زیادی روی سرور میوفته. چه راه حلی به ذهنتون میرسه؟
فرم توسط یک دستکتاپ اپلیکیشن بصورت واقعی و نه با ارسال دیتا به آدرس متد اکشن ، سابمیت میشه. یعنی روش های مرسوم مثل هیدن کپچا ، آنتی csrf و ... منظور این پرسش نیست.
لاراول یه چیزی داره به نام throttle که میتونی ازش استفاده کنی. یه middleware هست که بررسی میکنه یه درخواست تعدادش توی یه بازه زمانی خاص (که خودت مشخص میکنی) از یه حدی بالاتر نره. اگه بالاتر بره اون کاربر رو تا یه تایمی مسدود میکنه.
خب کَش ها به همین درد می خورند. شما می تونید هر بار که user فرم رو سابمیت می کنه توی کش ذخیره کنید و اگه مثلا از یه حدی زیاد شد اجازه بهش ندید
@h.r.hassani
اوکی ، بیا این روش و یکم بازش کنیم ، فرض مثال روی ردیس آی پی طرفو نگه میدارم و این بررسی رو انجام میدم. و بعد از اون کاربر مثلا با apache بن میشه.
انجام همین پروسه مدام ریسورس میگیره از سرور. (البته قطعا به دلیل درگیر نشدن io خیلی بهینه تر از کوئری زدن به دیتابیسه)
اوه اوه این کار توی ریکوئست های بالا واقعا میتونه منجر به قطع شدن سرویس بشه.
به نظرم این موضوع جالبه ، به تحقیق اش می ارزه. بررسی کنیم ببینیم سایتای بزرگ چیکار میکنن.
@dinihooman
پس لاراول چجوری این کار رو می کنه و مشکلی هم نداره؟؟
ولی کلا برای کنترل این کار مجبور resource بیشتری مصرف کنی
سلام وقتتون بخیر.
با یه نگاه به کدای لاراول میشه فهمید که لاراول داره از کش استفاده میکنه برای این که بفهمه کاربر چند تا درخواست توی مدت زمانی که تایین میکنید.
سه تا فایل مهم هست که با نگاه کردن به اونا میتونید متوجه بشید که چه شکلی داره کار میکنه سیستم throttle لاراول.
این فایل اون میدلویری هست که چک میکنه:
Illuminate\Routing\Middleware\ThrottleRequests.php
حالا اگر دقت بکنید این فایل از train ی استفاده کرده به نام InteractsWithTime
که namespaceش اینه:
Illuminate\Support\InteractsWithTime.php
فایل بالا کار خاصی نمیکنه یه سری توابع کمک کننده برای کار با زمان تو مواردی مثل throttle هست.
و در آخر توی کانستراکتور میدلویری که بالا گزاشتم رو اگر نگاه کنیم، یک کلاسی رو اینجکت کرده به اسم RateLimiter که namespaceش این هست:
Illuminate\Cache\RateLimiter
کارای اصلی رو توی سیستم throttle همین سه تا فایل ( در واقع دو تا چون دومی خیلی مربوط به throttle نمیشه ) انجام میدن.
فایل اول که middleware هست یعنی نقطه آغازش میشه اون تابع handle که داره از اونجا اگر پله پله برید جلو کاملا متوجه میشید.
اگر خواستید تغییری توش ایجاد کنید خودتون یک middleware بسازید و کدهای اون رو داخلش کپی کنید، بعدش تغییرات مورد نظرتون رو بدید و middleware رو داخل kernel اضافه کنید.
در کل throttle لاراول خیلی قدرتمنده و اونجوری هم نیست که بگیم منابع زیاد از سرور میخواد. نه موقعی که از فایل استفاده میکنه و نه حتی موقعی که از چیزهایی مثل redis استفاده میکنه. ( در واقع مدیریت منابع رو خوب انجام میده )
این مقاله هم میتونه کمکتون کنه بخونیدش به نظرم.
و در آخر هم اگر خودتون میخواید پیادش کنید توی یه زبان یا ابزار دیگه واقعا کار سختی نیست یه نگاه به همین کدای لاراول بندازید کلیتش رو متوجه میشید و بعدش میتونید شخصیسازیش کنید و ببرید توی یک ابزار یا زبان دیگه.
@MehdiAghighi
بیا اینو تحلیل کنیم ،
یه سوال دارم درباره ساختار درونی این Middleware :
Throttle اطلاعات هرکاربر که چندبار در چه زمانی لاگین شده رو کجا ذخیره میکنه؟ روی دیتابیس ، فایل ، ردیس یا ...
تا اونجایی که من از کدها فهمیدم از فاساد Cache استفاده کرده. خب پس یعنی از هر Cache Driver که تایین کرده باشید استفاده میکنه. یعنی هم دیتابیس هم فایل هم ردیس هم هر درایور دیگهای که بخواید.
حتی خودتون هم میتونید درایوری که دوست دارید رو بسازید. مثلا توی گیتهاب برای mongoDB یه چیزایی هست.
جدا از امکانات لاراول برای این کار (throttle) خودت هم میتونی همچین چیز هایی رو بررسی کنی.
مثلا درخواست های ۱ ساعت آخر رو در کش داشته باشی و درخواست جدید میرسه چک کنی که چندمین درخواست اون کاربر در ۵ دقیقه گذشته هست..
کاری که لاراول هم کم و بیش به همین شکل (البته خیلی شیوا تر) انجام میده.
عزیز ، به نظر خودت چجوری کشی برای این منظور بهتره؟
میدونی دنبال اینم تا جای ممکن برای چک کردن این مورد به دیتابیس کوئری نزنم ، چون فرقی نمیکنه به کاربر اجازه انجام کارش داده میشه یا نه ، به هرحال برای سیستم سرباز هزینه ای ایجاد میکنه.
فایل به نظر من بدتر از دیتابیس هست ، چون io بیشتر درگیر میشه. تا اینجا که سرچ کردم ردیس بهترین گزینه بوده ، ولی میخوام ببینم سولوشن بهتری هم هست که من نمیشناسم.
فرض مثال شاید انجین ایکش یا آپاچی خودشون یه راه حل برای این منظور داشته باشن (صرف نظر از فایروال های سخت افزاری) .
@dinihooman خواهش میکنم :)
ردیس یه نکته خیلی مهمش اینه که میتونی برای مقدارهایی که ذخیره میکنی expire time بزاری و خب این موضوع هم خیلی میتونه کمکت کنه.
تابع INCR که داره هم که برای این کار خیلی خوبه ....
آیا مایل به ارسال نوتیفیکیشن و اخبار از طرف راکت هستید ؟