Lỗi throttle trong Laravel
Chào mọi người, mình có gặp vấn đề về throttle trong Laravel mong mọi người giúp đỡ. Trong file Kernel của laravel có cái này 'throttle:60,1' Mình hiểu là mỗi user trong một phút thì chỉ gửi tối đa 60 request lên server nhưng thực tế khi mình deploy lên thì khi một user nào đó trong hệ thống thực hiện quá 60 request trong vòng 1 phút thì server die luôn trong 1 phút, 1 phút sau server mới active lại. Mình comment dòng đó đi thì ok, nhưng nếu comment dòng đó thì nếu một con bot nào đó nó có thể thực hiện 1 triệu request trong vòng 1 phút thì server cũng chết, nên cũng không ổn. Mong mọi người giúp đỡ, thanks
2 ANSWERS
cái này 'throttle:60,1'
- TH1: Nếu đã đăng nhập: Là cho phép user được truy cập tối đa 60 request / 1 phút tới các apis tương ứng.
- TH2: Nếu chưa đăng nhập: Là cho phép client có IP
xxx.xxx.xxx.xxx
được truy cập tối đa 60 request / 1 phút tới các apis tương ứng.
Thứ tự check: Check TH1 sau đó mới check TH2.
Nếu bạn test dưới local, chưa đăng nhập thì tất cả các client đều chung IP loopback nên có thể làm bạn nghĩ là cả server die luôn.
cái này 'throttle:60,1'
Chú ý: Nếu được sử dụng ngay trong kernel mặc định thì tức là nó đang áp dụng cho toàn bộ apis.
Cảm ơn bạn
Middleware sử dụng RateLimiter
, một component của Laravel Cache system. Bạn thử kiểm tra xem cache driver hiện tại bạn đang dùng là gì. Kiểm tra file config/cache.php
và file .env
nếu cần. Nếu driver là array thì mình nghĩ sẽ có vấn đề Có thể nó không gây ra lỗi của bạn mà chỉ đơn giản là middleware đó sẽ không có tác dụng thôi.
Nếu không phải do cache driver thì mình nghĩ bạn đang sử dụng middleware đó cho toàn bộ các route. Hiểu đơn giản là nếu bạn dùng middleware đó cho một nhóm các route thì khi một route bị rate limited các route khác cũng tèo luôn.
Ví dụ:
Route::middleware('throttle:5,1')->group(function () {
Route::get('/foo', function () {
return 'Bar';
});
Route::get('/bar', function () {
return 'Baz';
});
});
Sau 5 lần truy cập /foo
liên tiếp trong 1 phút, exception sẽ throw và 429 error code sẽ trả về. Lúc này bạn truy cập /bar
cũng tèo luôn
Nguyên nhân là Laravel sẽ dùng một key trong cache để xác định xem việc truy cập route có khả khi không - <key>:timer
. Cache key đó được xác định bởi một hash string - dùng sha1
với request signature. Signature đó được xác định bởi identifier của user (thường là ID) nếu đã đăng nhập. Hoặc là một string có dạng <domain>|<ip>
nếu chưa đăng nhập. Có thể thấy signature này không phân biệt các route trong một nhóm với nhau, nên một cái tèo thì những cái khác cũng tèo.
Thế nên nếu bạn wrap tất cả các route trong middleware đó thì một cái tèo thì bạn sẽ không truy cập được route nào nữa
Bạn chỉ nên sử dụng middleware đó cho một hoặc một nhóm các route nhất định nào đó thôi.
Chú ý là kể cả khi bạn định nghĩa tham số khác nhau cho các route group khác nhau. Nếu các requests đến từ cùng 1 user hay 1 IP thì số lượng request có thể thực hiện sẽ phụ thuộc nhau và không dễ để xác định chính xác. Túm lại là do request signature không đổi sau mỗi request vì chúng ta sử dụng hash....
Cảm ơn bạn