11
votes

Comment limiter la concurrence lors de l'utilisation d'acteurs à Scala?

Je viens de Java, où je voudrais soumettre Runnable s à un exécutantservice soutenu par un pool de threads. Il est très clair dans Java Comment définir des limites sur la taille de la piscine de fil.

Je suis intéressé à utiliser des acteurs Scala, mais je ne suis pas clair sur la façon de limiter la concurrence.

Disons simplement, hypothétiquement, que je crée un service Web qui accepte des "emplois". Un travail est soumis avec POST Demandes, et je veux que je souhaite que mon service s'effectue le travail, puis retournez immédiatement 202 accepté - c'est-à-dire que les travaux sont gérés de manière asynchrone.

Si j'utilise des acteurs pour traiter les travaux dans la file d'attente, comment puis-je limiter le nombre d'emplois simultanés traités?

Je peux penser à quelques façons différentes de s'approcher de cela; Je me demande s'il y a une meilleure pratique de la communauté, ou du moins, certaines approches clairement établies qui sont un peu standard dans le monde Scala.

Une approche que j'ai pensée est d'avoir un seul acteur de coordinateur qui gérerait la file d'attente de travail et les acteurs de traitement d'emploi; Je suppose qu'il pourrait utiliser un champ Int simple pour suivre combien d'emplois sont en cours de traitement. Je suis sûr qu'il y aurait des gotchyas avec cette approche, cependant, comme en veillant à suivre lorsqu'une erreur se produit afin de décrémenter le nombre. C'est pourquoi je me demande si Scala fournit déjà une approche plus simple ou plus encapsulée.

BTW J'ai essayé de poser cette question un moment il y a mais je l'ai mal demandé.

merci!


0 commentaires

3 Réponses :


5
votes

Vous pouvez remplacer les propriétés du système acteurs.maxpoolsize et acteurs.corepoolsize qui limitent la taille de la piscine de fil de l'acteur, puis lancez autant de travaux à la piscine que votre Les acteurs peuvent gérer. Pourquoi pensez-vous que vous devez manette des gaz vos réactions?


3 commentaires

Très utile, merci! Je ne suis pas sûr que j'utilise le terme papillon , mais de toute façon, il y a des moments où on doit contraindre le nombre de "processus" simultanés parce que le travail qu'ils effectuent est à forte intensité de ressources.


Cette approche pourrait ne pas donner le résultat souhaité. Il permettra à des emplois d'être mis en file d'attente jusqu'à ce que la JVM manque de mémoire. Limiter le nombre de threads que les acteurs peuvent utiliser ne limitera que le nombre d'emplois réellement exécutés simultanément. J'ai produit des erreurs OOM en générant des travaux plus rapidement que les acteurs ne peuvent le faire avant, de sorte que vous devez faire attention.


Je pense qu'un inconvénient de cette approche est que c'est global. Parfois, j'ai différents types de processus que je dois exécuter, qui ont des niveaux différents d'utilisation des ressources - avec des pools de fil Java, je peux facilement utiliser différentes piscines avec des paramètres différents. Avec acteurs.maxpoolsize , je ne peux utiliser qu'un seul numéro pour tous les acteurs, car ils sont tous alimentés par la même piscine de fil, non?



7
votes

Je vous encourage vraiment à jeter un coup d'œil à Akka, une mise en œuvre de l'acteur alternatif pour Scala.

http://www.akkasource.org

AKKA a déjà une intégration JAX-R-RS [1] et vous pourriez utiliser cela de concert avec un voleur [2] pour accélérer le nombre d'actions à Parallell:

[1] http://doc.akkasource.org/rest [2] http: // github. com / jboner / akka / blob / maître / akka-mods / src / Main / Scala / motifsCala


1 commentaires

Certains des liens sont morts.



3
votes

Vous avez vraiment deux problèmes ici.

Le premier consiste à garder le piscine de fil utilisé par les acteurs sous contrôle. Cela peut être fait en définissant les acteurs de la propriété système.maxpoolsize.

La seconde est une croissance fuguelle dans le nombre de tâches soumises au pool. Vous pouvez ou non être préoccupé par celui-ci, mais il est entièrement possible de déclencher des conditions de défaillance telles que des erreurs de mémoire et, dans certains cas, des problèmes potentiellement plus subtils en générant trop de tâches trop rapides.

Chaque fil de travail maintient une détresse de tâches. La dequeuse est implémentée comme une matrice que le fil du travailleur élargira de manière dynamique jusqu'à une certaine taille maximale. Dans 2.7.x, la file d'attente peut se développer assez grande et j'ai vu que la gâchette est de la gâchette des erreurs de mémoire lorsqu'elle est combinée avec de nombreux threads simultanés. La taille maximale de Dequeue est plus petite 2.8. La dequeuse peut également remplir.

Répondre à ce problème, vous devez contrôler le nombre de tâches que vous générez, ce qui signifie probablement une sorte de coordinateur que vous avez décrit. J'ai rencontré ce problème lorsque les acteurs qui initient une sorte de pipeline de traitement de données sont beaucoup plus rapides que ceux plus tard dans le pipeline. En contrôlant le processus, je dispose habituellement les acteurs plus tard dans les acteurs de la chaîne ping auparavant dans la chaîne tous les messages X et que celles-ci plus tôt dans la chaîne s'arrêtent après les messages X et attendez le dos de Ping. Vous pouvez également le faire avec un coordinateur plus centralisé.


0 commentaires