Asked Jun 1st, 2018 4:33 AM 513 0 2
  • 513 0 2
+2

Lỗi throttle trong Laravel

Share
  • 513 0 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 ANSWERS


Answered Jun 1st, 2018 7:54 AM
Accepted
+5

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.

Share
Van Hung @vhung
Jun 2nd, 2018 7:19 AM

Cảm ơn bạn

0
| Reply
Share
Answered Jun 1st, 2018 5:01 PM
+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....

Share
Van Hung @vhung
Jun 2nd, 2018 7:19 AM

Cảm ơn bạn

0
| Reply
Share