2012-04-16 14 views
12

Sto sviluppando una semplice API REST utilizzando Spring 3 + Spring MVC. L'autenticazione avverrà tramite OAuth 2.0 o l'autenticazione di base con un token client utilizzando Spring Security. Questo è ancora in discussione. Tutte le connessioni saranno forzate tramite una connessione SSL.Come implementare la limitazione della velocità basata su un token client in primavera?

Ho cercato informazioni su come implementare la limitazione della velocità, ma non sembra che ci siano molte informazioni là fuori. L'implementazione deve essere distribuita, in quanto funziona su più server web.

Ad esempio, se ci sono tre server API A, B, C e i client sono limitati a 5 richieste al secondo, un client che esegue 6 richieste come tali troverà la richiesta C respinta con un errore.

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

Ha bisogno di lavoro basato su un token incluso nella richiesta, come un client può essere fare le richieste per conto di molti utenti, e ogni utente dovrebbe essere limitato tasso piuttosto che l'indirizzo IP del server.

L'installazione sarà costituita da più (2-5) server Web dietro un bilanciatore del carico HAProxy. C'è una Cassandra supportata, e viene usata la memcached. I server Web saranno in esecuzione su Jetty.

Una possibile soluzione potrebbe essere quella di scrivere un filtro Spring Security personalizzato che estrae il token e verifica quante richieste sono state fatte con esso negli ultimi X secondi. Questo ci consentirebbe di fare alcune cose come diversi limiti di velocità per diversi clienti.

Qualche suggerimento su come può essere fatto? Esiste una soluzione esistente o dovrò scrivere la mia soluzione? Non ho mai fatto molta infrastruttura di siti web prima d'ora.

+0

Sei sulla strada giusta con l'idea del filtro. Dal momento che stai già usando memcached, dovrebbe essere semplice. – sourcedelica

+0

L'aspetto di un filtro potrebbe essere la soluzione giusta. Trovato un utile articolo sull'implementazione di un sistema di bucket per intervalli in modo da poter controllare l'uso delle API negli ultimi X minuti/secondi -> http://chris6f.com/rate-limiting-with-redis. Usa i redis ma i principi dovrebbero essere simili a memcache o cassandra. –

risposta

0

Eviterei di modificare il codice del livello dell'applicazione per soddisfare questo requisito se possibile.

Ho avuto uno sguardo attraverso la documentazione di HAProxy LB non troppo ovvio lì, ma il requisito potrebbe garantire un'indagine completa degli ACL.

Mettere HAProxy da un lato, una possibile architettura è mettere un Apache WebServer in primo piano e utilizzare un plug-in Apache per limitare la velocità. Le richieste over-the-limit vengono rifiutate in anticipo e i server delle applicazioni nel tier dietro ad Apache vengono quindi separati dai problemi di limite di velocità rendendoli più semplici. Si potrebbe anche considerare di servire contenuto statico dal server Web.

vedere la risposta a questa domanda How can I implement rate limiting with Apache? (requests per second)

Spero che questo aiuta. Rob

+1

Grazie per la risposta. Il progetto attualmente non utilizza Apache WebServer, Jetty è utilizzato per la distribuzione di file war. Esistono numerose guerre esistenti che costituiscono l'app corrente e l'API sarà semplicemente un'altra applicazione Web eseguita in Jetty. Sarebbe un bel po 'di sforzo passare ad Apache, quindi sto cercando di evitarlo se possibile. Sembra anche che le mod di Apache siano focalizzate su IP piuttosto che su token limitanti. Farlo nel codice app è un problema, ma sembra offrire il massimo controllo. Potrebbe essere lento, ma non è pensato per bloccare gli attacchi DDoS. –

0

È possibile impostare i limiti di velocità in vari punti del flusso (generalmente più in alto, meglio è) e l'approccio generale che si ha ha molto senso. Un'opzione per l'implementazione è l'utilizzo di 3scale per farlo (http://www.3scale.net) - calcola i limiti, l'analisi, la chiave gestita ecc. E funziona con un plug-in di codice (il plug-in Java è qui: https://github.com/3scale/3scale_ws_api_for_java) che spinge o mettendo qualcosa come Varnish (http://www.varnish-cache.org) nella pipeline e con i limiti di velocità applicati.

0

Stavo pensando anche alle soluzioni simili un paio di giorni fa.Fondamentalmente, preferisco la soluzione "controllata centralmente" per salvare lo stato della richiesta del client nell'ambiente distribuito.

Nella mia applicazione, utilizzo un "session_id" per identificare il client di richiesta. Quindi crea un filtro servlet o molla HandlerInterceptorAdapter per filtrare la richiesta, quindi controlla "session_id" con il repository dati controllato centralmente, che può essere memcached, redis, cassandra o zookeeper.