2014-05-14 2 views
0

Cette question ne concerne pas seulement le rubis.accès simultané à l'API avec des limites

J'ai beaucoup de travailleurs en cours d'exécution pour créer de nombreuses connexions à l'API externe. Cette API a une limite.
À l'heure actuelle, j'utilise sidekiq et redis pour limiter l'accès.
c.-à-d. À chaque accès à l'API que j'ai évalué comme étant un travailleur.
Ensuite, le travail est démarré il vérifier quand était la dernière fois pour accéder à l'API, si est plus tôt que cette API le permet, le travailleur est replanifié, sinon il touche le temps dans redis et demande d'exécution.

ex:

def run_or_schedule 
    limiter = RedisLimiter.new(account_token) 
    if limiter.can_i_run? 
    limiter.like 
    run 
    else 
    ApiWorker.perform_at(limiter.next_like, *params) 
    end 
end 

Le problème est que je crée beaucoup demande et ils plusieurs fois reprogrammée.

Peut-être que quelqu'un peut recommander une meilleure solution?

Peut-être existe-t-il des modèles de conception pour cela?

Répondre

1

Une alternative à l'approche d'interrogation que vous utilisez serait d'avoir un supervisor. Ainsi, au lieu de demander à chaque travailleur de traiter lui-même la question, vous avez un autre objet/travailleur/processus qui décide du moment de l'exécution du prochain travailleur.

Si l'API impose une limite de temps entre les demandes, ce superviseur peut s'exécuter aussi souvent que le délai le permet.

Si la limite est plus complexe (par exemple, le nombre total de requêtes par intervalle X), vous pouvez faire en sorte que le superviseur s'exécute constamment et qu'il frappe un bloc limite (veille) pendant cette durée. Lors de la reprise, il pourrait continuer avec le prochain travailleur de la file d'attente. Un avantage apparent de cette approche est que vous pouvez ignorer la surcharge liée à chaque instanciation individuelle, en vérifiant elle-même si elle doit être exécutée et en étant replanifiée si elle ne l'est pas.

1

Vous pouvez utiliser une file d'attente et un thread dédié qui envoie des événements (lorsqu'il y a des attentes) au débit maximum autorisé.

Dites que vous pouvez envoyer un appel API à chaque seconde, vous pouvez effectuer les opérations suivantes:

class APIProxy 
    def like(data) 
    @like_queue << data 
    end 

    def run 
    Thread.new do 
     @like_queue = Queue.new 
     loop do 
     actual_send_like @like_queue.pop 
     sleep 1 
     end 
    end 
    end 

    private 
    def actual_send_like(data) 
    # use the API you need 
    end 
end 
Questions connexes