Número razonable de subprocesos para el grupo de subprocesos que ejecutan solicitudes de servicio web

StackOverflow https://stackoverflow.com/questions/1028707

Pregunta

Al crear un objeto Executor FixedThreadPool en Java, debe pasar un argumento que describa el número de subprocesos que el Ejecutor puede ejecutar simultáneamente. Estoy creando una clase de servicio cuya responsabilidad es procesar una gran colección de números de teléfono. Para cada número de teléfono, necesito ejecutar el servicio web (ese es mi cuello de botella) y luego guardar la respuesta en un hashmap.

Para que este cuello de botella sea menos perjudicial para el rendimiento de mi servicio, he decidido crear una clase Worker que recupere elementos no procesados ??y los procese. Worker class implementa la interfaz Runnable y ejecuto Workers utilizando Executor.

El número de trabajadores que se pueden ejecutar al mismo tiempo depende del tamaño de Executor FixedThreadPool. ¿Cuál es el tamaño seguro para un ThreadPool? ¿Qué puede suceder cuando creo FixedTheradPool con algún número grande como argumento?

¿Fue útil?

Solución

Si cada subproceso de trabajo necesita realizar una llamada de servicio web, entonces el número de subprocesos en su grupo debe verse fuertemente influenciado por la cantidad de solicitudes simultáneas que su servicio web puede manejar. Más hilos que eso no harán más que abrumar al servicio web.

Otros consejos

Algo que podría considerarse es mirar

Runtime.getRuntime().availableProcessors()

que da algunas indicaciones sobre cuántos hilos tendrían sentido para el sistema.

He leído en alguna parte que el número óptimo de subprocesos es el número de núcleos * 25. Parece que .NET usa esto como predeterminado para ThreadPool. Sin embargo, si tiene un gran número de llamadas al servicio web, será mejor que use un solo hilo y verifique una lista de llamadas al servicio web para obtener una respuesta. Cuando llegue la respuesta, simplemente procese la entrada y elimínela de la lista.

Si cada cálculo es equivalente a una llamada a un servicio web, entonces debe considerar cuánta carga está poniendo en ese servicio / cuántas conexiones concurrentes ese servicio tolerará o sería permitido por los propietarios de los servicios. La mayoría de los servicios de acceso público esperarían solo una conexión de este tipo de un solo usuario a la vez. Si es posible, comuníquese con los propietarios de los servicios para conocer sus políticas de uso. El número de tales conexiones determinará el número de hilos que puede usar.

Si tiene acceso de desarrollador al servicio web, considere crear una función por lotes para verificar múltiples números de teléfono en una sola llamada.

En .NET más reciente hay un ThreadPool que puede crecer y reducirse según su propio perfil de rendimiento. Desafortunadamente, la versión de Java es fija o crece hasta un límite basado en el trabajo entrante.

Una vez tuvimos preocupaciones similares. Nuestra solución fue permitir que el cliente ajustara el tamaño del grupo y ajustara el rendimiento como quisiera.

Puede haber algunas propiedades de red y datos consideradas para el tamaño del grupo de operaciones de E / S: ancho de banda de red, tamaños de mensaje, tiempo de procesamiento y estilo del servicio web, número de núcleos locales.

Supongamos que el servicio web es infinitamente escalable y que a nadie le importará que lo esté enviando spam con solicitudes. Supongamos también que las respuestas del servicio web están en el rango de 1 segundo, mientras que el tiempo de procesamiento local es de 5 milisegundos.

El rendimiento se maximiza cuando tiene la misma cantidad de subprocesos ocupados que los núcleos de procesamiento.

Bajo estas suposiciones, no podrá maximizar el rendimiento en un procesador de múltiples núcleos para cualquier tamaño razonable de grupo de subprocesos. Para lograr transacciones máximas por segundo, debe romper el hilo por modelo de conexión. Busque E / S sin bloqueo (NIO) mencionadas anteriormente o una implementación Java del patrón de token de finalización asincrónica (finalización de E / S en Windows).

Tenga en cuenta que la memoria de pila que está reservada para cada subproceso creado en realidad solo está reservado espacio de direcciones , no memoria asignada o comprometida real. A medida que la pila intenta crecer, se generan excepciones, lo que da como resultado que la memoria de la pila se comprometa a demanda. La consecuencia es que solo es realmente relevante para los administradores de memoria de 32 bits. Para la memoria de 64 bits, tiene un gran espacio de direcciones aunque solo respalde una pequeña parte de ese espacio con memoria física. Al menos, así es como entiendo que funciona Windows, no estoy seguro sobre el mundo de Unix.

No olvide que cada hilo que cree también exigirá memoria para su tamaño de pila. Por lo tanto, la creación de un grupo de subprocesos afectará la huella de memoria de su proceso (tenga en cuenta que algunos grupos no crean los subprocesos hasta que sean realmente necesarios, por lo que al inicio no verá ningún aumento de memoria).

Este tamaño de pila se puede configurar a través de -Xss (similar a -Xmx etc.). Creo que el valor predeterminado es 512Kb por hilo. Por el momento no puedo encontrar ninguna autoridad para confirmar eso.

Me pregunto si sería mejor usar NIO en lugar de subprocesos, ya que su factor limitante será el servidor de servicios web + cuello de botella de red, no la CPU del cliente.

De lo contrario, como máximo no debe exceder el número de conexiones simultáneas que su servicio web puede admitir.

Si está haciendo cálculos pesados, digamos para manipulaciones de matriz paralela, entonces la regla general es tener el número de subprocesos para el número de procesadores.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top