2010-02-24 11 views
10

La mia applicazione effettua richieste di servizi Web; c'è una percentuale massima di richieste che il provider gestirà, quindi ho bisogno di rallentarle.Posso limitare le richieste effettuate da un'app distribuita?

Quando l'app funzionava su un singolo server, lo facevo a livello di applicazione: un oggetto che tiene traccia di quante richieste sono state fatte finora, e aspetta se la richiesta corrente lo fa supera il massimo consentito caricare.

Ora, stiamo migrando da un singolo server a un cluster, quindi sono in esecuzione due copie dell'applicazione.

  • non riesco a tenere il controllo per il carico massimo al codice dell'applicazione, in quanto i due nodi combinati potrebbero superare il carico consentito.
  • Non posso semplicemente ridurre il carico su ciascun server, perché se l'altro nodo è inattivo, il primo nodo può inviare più richieste.

Questo è un ambiente JavaEE 5. Qual è il modo migliore per limitare le richieste inviate dall'applicazione?

+2

solo curioso, stai usando una struttura speciale come Terracota? –

+0

@Pablo: No. Stiamo migrando da un singolo server JBoss su un server dedicato a un WebLogic 10.3 ospitato configurato con due nodi. – Leonel

risposta

5

Poiché si è già in un ambiente Java EE, è possibile creare un MDB che gestisca tutte le richieste al servizio web basato su una coda JMS. Le istanze dell'applicazione possono semplicemente inviare le loro richieste alla coda e MDB le riceverà e chiamerà il servizio web.

La coda può essere effettivamente configurata con il numero appropriato di sessioni che limiterà l'accesso simultaneo al servizio web dell'utente, pertanto la limitazione viene gestita tramite la configurazione della coda.

I risultati possono essere restituiti tramite un'altra coda (o anche una coda per istanza dell'applicazione).

+0

Sì, dato che ero già su un ambiente JavaEE, la coda JavaEE era la soluzione più semplice e non avevo bisogno di aggiungere altre dipendenze. – Leonel

1

Molti modi per farlo: potresti avere un "Agente di coordinamento" che è responsabile della consegna di "token" ai server. Ogni "token" rappresenta un'autorizzazione per eseguire un'attività, ecc. Ogni applicazione deve richiedere "token" per effettuare chiamate.

Una volta che un'applicazione scarica i token, deve chiedere ancora qualcosa prima di procedere nuovamente al servizio Web.

Naturalmente tutto ciò si complica quando ci sono dei requisiti per quanto riguarda i tempi di ciascuna chiamata effettuata da ogni applicazione a causa della concorrenza verso il servizio Web.

È possibile fare affidamento su RabbitMQ come framework di messaggistica: i binding Java sono disponibili.

+0

+1 perché non ero a conoscenza di RabbitMQ che ha anche binding .net. – tobsen

1

I nodi N devono comunicare. Esistono varie strategie:

  • broadcast: ogni nodo trasmetterà a tutti gli altri che sta effettuando una chiamata macking e tutti gli altri nodi ne terranno conto. I nodi sono uguali e mantengono il conteggio globale individuale (ogni nodo conosce la chiamata di ogni altro nodo).
  • nodo principale: un nodo è speciale, il suo master e tutti gli altri nodi richiedono il permesso al master prima di effettuare una chiamata. Il master è l'unico che conosce il conteggio globale.
  • master dedicato: uguale al master, ma il "master" non effettua chiamate su proprio livello, è solo un servizio che tiene traccia delle chiamate.

A seconda di quanto si prevede di scalare in seguito, l'una o l'altra strategia potrebbe essere la soluzione migliore. Per i 2 nodi viene trasmesso il più semplice, ma con l'aumentare del numero di nodi i problemi iniziano a montare (trascorrerai più tempo a trasmettere e rispondere alle emittenti piuttosto che a fare richieste WS).

Come comunicano i nodi, dipende da voi. È possibile aprire una pipe TCP, è possibile broadcats UDP, è possibile eseguire un WS completo per questo scopo da solo, è possibile utilizzare un protocollo di condivisione file. Qualunque cosa tu faccia, non sei più all'interno di un processo, quindi si applicano tutti gli fallacies of distributed computing.

1

Questo è un problema interessante e la difficoltà della soluzione dipende in un certo grado da quanto rigoroso si vuole essere sulla limitazione.

La mia solita soluzione a questo è JBossCache, in parte perché viene fornito con JBoss AppServer, ma anche perché gestisce l'attività piuttosto bene. Puoi usarlo come una sorta di hashmap distribuita, registrando le statistiche di utilizzo a vari gradi di granularità. Gli aggiornamenti possono essere eseguiti in modo asincrono, quindi non rallentano le cose.

JBossCache viene solitamente utilizzato per il caching distribuito pesante, ma mi piace per questi lavori più leggeri. È pura java, e non richiede alcun gioco con la JVM (a differenza della terracotta).

2

Si consiglia di utilizzare beanstalkd per pompare periodicamente una raccolta di richieste (lavori) in un tubo (coda), ciascuna con un ritardo appropriato. Qualsiasi numero di thread o processi "worker" attenderà che la richiesta successiva sia disponibile, e se un lavoratore finisce presto può raccogliere la richiesta successiva. Il lato negativo è che non esiste un bilanciamento del carico esplicito tra i lavoratori, ma ho trovato che la distribuzione delle richieste dalla coda è stata ben bilanciata.

0

Hystrix è stato progettato per quasi lo scenario esatto che stai descrivendo. È possibile definire una dimensione del pool di thread per ciascun servizio in modo da disporre di un numero massimo impostato di richieste simultanee e accodare le richieste quando il pool è pieno. È anche possibile definire un timeout per ciascun servizio e quando un servizio inizia a superare il timeout, Hystrix rifiuterà ulteriori richieste per quel servizio per un breve periodo di tempo al fine di dare al servizio la possibilità di rimettersi in piedi. C'è anche il monitoraggio in tempo reale dell'intero cluster tramite Turbine.

Problemi correlati