Yêu cầu thg 6 1, 2018 4:33 SA 4692 2 2
  • 4692 2 2
+3

Lỗi throttle trong Laravel

Chia sẻ
  • 4692 2 2

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 CÂU TRẢ LỜI


Đã trả lời thg 6 1, 2018 7:54 SA
Đã được chấp nhận
+6

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.

Chia sẻ
Avatar Van Hung @vhung
thg 6 2, 2018 7:19 SA

Cảm ơn bạn

Đã trả lời thg 6 1, 2018 5:01 CH
+2

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....

Chia sẻ
Avatar Van Hung @vhung
thg 6 2, 2018 7:19 SA

Cảm ơn bạn

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí