Consigli per la progettazione del limitatore di velocità delle richieste API?

7

Sono in fase di pianificazione di un'applicazione web che fa un uso pesante dei dati recuperati dall'API REST di terze parti. Questi dati sono memorizzati nella cache sul server e richiesti dai client tramite AJAX. L'API REST ha un limite di velocità e prevedo di utilizzare lo schema del token bucket per aderire ad esso. Tuttavia, ho difficoltà a trovare un modo sicuro per la memorizzazione del valore del bucket. Per questo motivo, sto considerando due tecnologie per le mie esigenze lato server. Io programma solo come hobby quindi ... tieni con me.

PHP

Qui, ho preso in considerazione l'ipotesi di inserire la variabile bucket nella cache APCu, ma non sono del tutto sicuro di quale thread-safe sia. Immagino uno scenario: c'è un gettone lasciato nel secchio. Il client A preleva i dati dalla cache, quindi il client B subito dopo. A nota ne rimane uno e sottrae un token, quindi B fa lo stesso, il bucket è a -1 ed entrambi pensano di essere chiari per richiedere. Se un mucchio di discussioni lo fa, io rompo il limite. È uno scenario realistico? C'è un modo migliore per implementare questo limite API a livello di sito (non per utente)? Preferirei non ricorrere a una sceneggiatura esterna.

node.js

Node sembra perfetto, data l'architettura del sito, ma è un enorme cambiamento nel modo di pensare. Ha solo un thread di esecuzione, e ci sono anche vars globali che i documenti dicono siano locali al modulo. Presumo che 'locale al modulo' significhi che è disponibile solo per quel modulo, ma 'globale' indica ogni volta che un modulo si presenta nella coda degli eventi, la variabile globale sarà lì. È questo il caso? In tal caso, quando il bucket è vuoto e il modulo deve attendere per effettuare la richiesta, ciò bloccherà tutto il resto del nodo, vero? E se ci sono più istanze node.js in esecuzione, il globale non è condiviso tra loro, vero? Ho visto diversi pacchetti npm per la limitazione della velocità, ma sembrano tutti per utente.

Ho altre domande sul nodo, ma questo post è già abbastanza lungo.

Qualche consiglio?

    
posta TseehnMarhn 18.12.2015 - 00:16
fonte

2 risposte

1

PHP

La cache in lettura / scrittura è una sezione critica . Dovrai proteggerlo con la tua scelta di mutua esclusione per impedire la falsa lettura che descrivi. Nel bene o nel male, il blocco in PHP non è semplice. La soluzione multipiattaforma utilizza un file (garantito per causare dolore se il tuo server è occupato). Oltre a ciò dipende dal sistema operativo e dalla configurazione del server. Puoi leggere ulteriori informazioni qui: link .

Node.js

Poiché il nodo è a thread singolo, non è necessario un blocco a meno che non si esegua un'operazione asincrona (I / O e relativi). Questo non risolve necessariamente tutti i tuoi problemi, comunque. Leggi di più sotto.

Tutte

Come descritto, hai un grande problema incombente. Vedo l'intuizione quando dici "... questo bloccherebbe tutto il resto del nodo, vero?" Non è esattamente il problema: puoi creare un'attesa che non blocchi. Ma l'attesa risolve i tuoi problemi? Non proprio. Se il tuo sito è molto occupato, ogni richiesta di attesa aumenta la possibilità che la prossima richiesta debba attendere. Le richieste si stanno accumulando ... Se c'è abbastanza traffico, le attese si allungheranno. Ci saranno dei timeout. Ci saranno torcendo le mani. Ci saranno lacrime.

Questo è un problema di pari opportunità. Né PHP né Node sono immuni. (In realtà, tutti sono vulnerabili a causa di una risorsa strozzata e dell'approccio che descrivi.) Una coda di messaggi non ti salva. Tutta la coda di un messaggio ti dà un mucchio di richieste in coda che sono in attesa . Abbiamo bisogno di un modo per eliminare le richieste!

Fortunatamente, questo può essere piuttosto diretto se spingiamo più responsabilità verso il browser. Con un po 'di re-jiggering, la risposta al browser può contenere uno stato e un risultato opzionale. Sul server, invia uno stato "di successo" e ottieni se ricevi un token API. Altrimenti, invia uno stato "non ancora". Nel browser, se la richiesta riesce, procedere normalmente. Altrimenti, procedi come ritieni opportuno. Se invii richieste in modo asincrono, puoi riprovare tra mezzo secondo, poi un secondo completo, quindi ... Ci sono grandi opportunità per dare il feedback degli utenti. Oltre all'ottimo feedback, questo approccio mantiene anche le risorse del server al minimo. Il server non è punito per il collo di bottiglia dell'API di terze parti.

L'approccio non è perfetto. Una caratteristica non così bella è che non è garantito che le richieste vengano risolte nell'ordine ricevuto. Dal momento che si tratta di un gruppo di browser che cercano e riprovano, un utente davvero sfortunato potrebbe continuamente perdere il proprio turno. Il che mi porta alla penultima soluzione ...

Apri il tuo wallet

Suppongo che la tua API di terze parti sia limitata perché è gratuita! (o poco costoso) Se vuoi davvero stupire i tuoi utenti, considera di pagare per un servizio migliore. Invece di ingegnerizzare il tuo modo di uscire dal problema (che è un po 'fico, un po' approssimativo), risolvi il problema con denaro contante. Ricorda, molte, molte operazioni che funzionano a buon mercato sembrano economiche. Se vuoi mantenere i tuoi utenti, non lo vuoi.

    
risposta data 19.12.2015 - 23:31
fonte
-1

.net ha la classe SemaphoreSlim per questo tipo di cose, è possibile utilizzare il modello singleton per renderlo globale. anche ConcurrentQueue e altri oggetti possono aiutare.

Tuttavia, ti rimane ancora il problema di cosa stai facendo con le richieste extra al di sopra del limite di velocità.

Ti consiglio di esaminare i framework Message Queue come msmq, rabbit, zeroMq ecc per aiutare con l'architettura generale.

Ciò che idealmente si desidera ottenere è una singola coda che l'applicazione può inviare richieste a più processi di lavoro a tariffa limitata (in qualsiasi tecnologia) che attirano e gestiscono le richieste.

Queste app di lavoro non si adattano bene alle piattaforme di hosting Web come IIS, PHP o NodeJS. Suggerirei un servizio Windows. (ma poi im .net) sembra che un demone unix sia l'equivoco in URSS e puoi usare il nodo per crearne uno:  ( link )

vedi anche questa domanda sul perché questo è difficile da fare in JS

link

PHP tuttavia ha un'implementazione del semaforo

link

    
risposta data 19.12.2015 - 15:09
fonte

Leggi altre domande sui tag