2010-02-22 10 views
11

Vengo de Java, donde enviaría Runnable a un ExecutorService respaldado por un grupo de subprocesos. En Java está muy claro cómo establecer límites para el tamaño del grupo de subprocesos.¿Cómo limitar la concurrencia al usar actores en Scala?

Estoy interesado en usar actores de Scala, pero no tengo claro cómo limitar la concurrencia.

Digamos, hipotéticamente, que estoy creando un servicio web que acepta "trabajos". Se envía un trabajo con las solicitudes POST, y quiero que mi servicio ponga en cola el trabajo y luego devuelva inmediatamente 202 Accepted, es decir, los trabajos se manejan de forma asíncrona.

Si uso actores para procesar trabajos en la cola, ¿cómo puedo limitar el número de trabajos simultáneos que se procesan?

Puedo pensar en algunas formas diferentes de abordar esto; Me pregunto si hay una mejor práctica de la comunidad, o al menos, algunos enfoques claramente establecidos que son un tanto estándar en el mundo de Scala.

Un enfoque en el que he pensado es tener un solo actor coordinador que administraría la cola de trabajos y los actores de procesamiento de trabajos; Supongo que podría usar un campo int simple para rastrear cuántos trabajos se están procesando actualmente. Sin embargo, estoy seguro de que habrá algunos gotchyas con ese enfoque, como asegurarse de seguir cuando ocurre un error para disminuir el número. Es por eso que me pregunto si Scala ya proporciona un enfoque más simple o más encapsulado a esto.

BTW Intenté hacer esta pregunta a while ago pero lo pedí mal.

Gracias!

Respuesta

5

Puede anular las propiedades del sistema actors.maxPoolSize y actors.corePoolSize que limitan el tamaño del grupo de subprocesos del actor y luego generan tantos trabajos en la agrupación como puedan manejar los actores. ¿Por qué crees que necesitas throttle tus reacciones?

+1

Muy útil, gracias! No estoy seguro de que usaría el término _throttle_, pero de cualquier forma, hay momentos en los que se necesita restringir el número de "procesos" simultáneos porque el trabajo que hacen es de recursos intensivos. –

+3

Este enfoque puede no dar el resultado deseado. Permitirá que los trabajos se pongan en cola hasta que la JVM se quede sin memoria. Limitar el número de subprocesos que los actores pueden usar limitará la cantidad de trabajos que se ejecutan de manera simultánea. He producido errores OOM generando trabajo más rápido de lo que los actores pueden hacerlo antes, así que debes tener cuidado. –

+2

Estoy pensando que una desventaja de este enfoque es que es global. A veces tengo diferentes tipos de procesos que necesito ejecutar que tienen diferentes niveles de utilización de recursos. Con los grupos de subprocesos de Java, puedo usar fácilmente diferentes grupos con diferentes configuraciones. Con 'actors.maxPoolSize', solo puedo usar un número único para todos los actores, porque todos ellos funcionan con el mismo grupo de subprocesos, ¿no? –

3

Realmente tiene dos problemas aquí.

Lo primero es mantener bajo control el grupo de subprocesos utilizado por los actores. Eso se puede hacer estableciendo la propiedad del sistema actors.maxPoolSize.

El segundo es un crecimiento descontrolado del número de tareas que se han enviado al grupo. Usted puede o no estar preocupado con este, sin embargo, es completamente posible desencadenar condiciones de falla como errores de falta de memoria y en algunos casos problemas potencialmente más sutiles al generar demasiadas tareas demasiado rápido.

Cada subproceso de trabajador mantiene una secuencia de tareas. La dequeue se implementa como una matriz que la cadena de trabajo se ampliará dinámicamente hasta un tamaño máximo. En 2.7.x la cola puede crecer bastante y he visto que desencadenan errores de memoria cuando se combinan con muchos hilos concurrentes. El tamaño máximo de dequeue es más pequeño 2.8. La dequeue también puede llenarse.

Para abordar este problema es necesario controlar la cantidad de tareas que genera, lo que probablemente signifique algún tipo de coordinador como lo ha descrito. Me he encontrado con este problema cuando los actores que inician un tipo de canalización de procesamiento de datos son mucho más rápidos que los que están más adelante en la tubería. Para controlar el proceso, por lo general, los actores que están más adelante en la cadena responden con un silbido a los actores de la cadena antes de cada X mensajes, y hacen que los primeros en la cadena se detengan después de los mensajes X y esperen a que vuelva el ping. También podría hacerlo con un coordinador más centralizado.

Cuestiones relacionadas