2012-04-16 34 views
12

Tôi đang phát triển một API REST đơn giản sử dụng Spring 3 + Spring MVC. Việc xác thực sẽ được thực hiện thông qua OAuth 2.0 hoặc auth cơ bản với mã thông báo ứng dụng khách sử dụng Spring Security. Đây vẫn là cuộc tranh luận. Tất cả các kết nối sẽ bị buộc thông qua kết nối SSL.Làm cách nào để triển khai giới hạn tốc độ dựa trên mã thông báo của khách hàng trong Spring?

Tôi đã tìm kiếm thông tin về cách triển khai giới hạn tốc độ, nhưng dường như không có nhiều thông tin ngoài đó. Việc triển khai cần phải được phân phối, trong đó nó hoạt động trên nhiều máy chủ web. Ví dụ: nếu có ba máy chủ api A, B, C và khách hàng được giới hạn trong 5 yêu cầu trong một giây, thì khách hàng yêu cầu 6 yêu cầu như vậy sẽ tìm thấy yêu cầu đối với C bị từ chối do lỗi.

A recieves 3 requests \ 
B receives 2 requests | Executed in order, all requests from one client. 
C receives 1 request /

Nó cần phải làm việc dựa trên một mã thông báo có trong yêu cầu, là một khách hàng có thể đưa ra yêu cầu thay mặt cho nhiều người dùng, và mỗi người dùng nên được giới hạn tốc độ chứ không phải là địa chỉ IP của máy chủ.

Thiết lập sẽ là nhiều (2-5) máy chủ web phía sau bộ cân bằng tải HAProxy. Có một Cassandra được hỗ trợ, và memcached được sử dụng. Các máy chủ web sẽ chạy trên Jetty.

Một giải pháp tiềm năng có thể là viết bộ lọc Spring Security tùy chỉnh để trích xuất mã thông báo và kiểm tra số lượng yêu cầu đã được thực hiện với nó trong X giây qua. Điều này sẽ cho phép chúng tôi thực hiện một số điều như giới hạn tốc độ khác nhau cho các khách hàng khác nhau.

Bất kỳ đề xuất nào về cách thực hiện? Có giải pháp hiện tại hay tôi sẽ phải viết giải pháp của riêng mình? Tôi đã không thực hiện rất nhiều cơ sở hạ tầng trang web trước đây.

+0

Bạn đang đi đúng hướng với ý tưởng bộ lọc. Vì bạn đã sử dụng memcached nên nó đơn giản. – sourcedelica

+0

Nó trông giống như một bộ lọc có thể là con đường để đi. Đã tìm thấy bài viết hữu ích về việc triển khai hệ thống thùng trong khoảng thời gian để bạn có thể kiểm tra việc sử dụng api trong X phút/giây cuối cùng -> http://chris6f.com/rate-limiting-with-redis. Nó sử dụng redis nhưng các nguyên tắc nên tương tự như memcache hoặc cassandra. –

Trả lời

0

Tôi sẽ tránh sửa đổi mã cấp ứng dụng để đáp ứng yêu cầu này nếu có thể.

Tôi đã xem qua tài liệu HAProxy LB không có gì quá rõ ràng ở đó, nhưng yêu cầu có thể đảm bảo điều tra đầy đủ các ACL.

Đưa HAProxy sang một bên, một kiến ​​trúc có thể là đặt một Máy chủ Web Apache lên phía trước và sử dụng một trình cắm thêm Apache để thực hiện giới hạn tốc độ. Các yêu cầu quá giới hạn bị từ chối ở phía trước và các máy chủ ứng dụng trong tầng phía sau Apache sau đó được tách ra khỏi các mối quan tâm giới hạn tốc độ làm cho chúng trở nên đơn giản hơn. Bạn cũng có thể xem xét phục vụ nội dung tĩnh từ Máy chủ Web.

Xem câu trả lời cho câu hỏi này How can I implement rate limiting with Apache? (requests per second)

Tôi hy vọng điều này sẽ hữu ích. Rob

+1

Cảm ơn câu trả lời. Dự án hiện không sử dụng Apache WebServer, Jetty được sử dụng để triển khai các tệp tin chiến tranh. Có một số cuộc chiến hiện tại tạo nên ứng dụng hiện tại và API sẽ chỉ đơn giản là một ứng dụng web khác chạy trong Jetty. Nó sẽ là một chút công bằng của nỗ lực để chuyển sang Apache, vì vậy tôi đang cố gắng tránh nó nếu có thể. Dường như các mods Apache tập trung vào IP thay vì giới hạn mã thông báo. Làm điều đó trong mã ứng dụng là một nỗi đau, nhưng dường như cung cấp sự kiểm soát nhiều nhất. Nó có thể chậm, nhưng nó không có ý định ngăn chặn các cuộc tấn công DDoS. –

0

Bạn có thể đặt giới hạn tốc độ tại các điểm khác nhau trong luồng (thường là càng cao càng tốt) và cách tiếp cận chung bạn có ý nghĩa rất nhiều. Một lựa chọn cho việc thực hiện là sử dụng 3scale để làm điều đó (http://www.3scale.net) - nó có giới hạn tốc độ, phân tích, khóa được quản lý vv và hoạt động với một plugin mã (plugin Java là ở đây: https://github.com/3scale/3scale_ws_api_for_java) Varnish (http://www.varnish-cache.org) trong đường ống và áp dụng giới hạn tốc độ.

0

Tốt nhất là bạn nên thực hiện ratelimit bằng cách sử dụng REDIS. Để biết thêm thông tin, vui lòng xem số điện thoại này Rate limiting js Example.

0

Tôi cũng nghĩ về các giải pháp tương tự cách đây vài ngày.Về cơ bản, tôi thích giải pháp "điều khiển trung tâm" để lưu trạng thái của yêu cầu của máy khách trong môi trường phân tán.

Trong đơn đăng ký của mình, tôi sử dụng "session_id" để xác định ứng dụng khách yêu cầu. Sau đó tạo một bộ lọc servlet hoặc Spring HandlerInterceptorAdapter để lọc yêu cầu, sau đó kiểm tra "session_id" với kho lưu trữ dữ liệu do trung tâm điều khiển, có thể được ghi nhớ, redis, cassandra hoặc zookeeper.

Các vấn đề liên quan