librelist archives

« back to archive

estrategia simple_one_for_one y terminate_child

estrategia simple_one_for_one y terminate_child

From:
Andrés F Vargas
Date:
2012-10-24 @ 13:53
Hola lista,

Me gustaría recibir feedback sobre el uso de gen_server, la estrategia
simple_one_for_one y termina_child:

Tengo una app, y la app representa un store de tripletas (digamosles
registros), entonces tengo un supervisor con una estrategia
simple_one_for_one y los workers son gen_server; tengo un módulo que
sirve de facade y expone el API pública, las funciones en ese módulo
lo que hacen es llamar start_child, usar el api del gen_server y luego
llaman terminate_child, el efecto es 1 proceso de gen_server por
llamada al API publica.

primera pregunta, esta eso bien? tengo dudas de si gen_server
implicitamente crea un nuevo proceso cada vez que se usa call o cast.

Lo que no quiero es un proceso manejando un millón de mensajes sino un
millon de procesos cada uno manejando un mensaje; ese es el
pensamiento correcto en Erlang?

tercera pregunta, cuando investigaba el asunto me tropecé mucha veces
con que no se podía usar terminate_child cuando el supervisor usa
simple_one_for_one, sin embargo desde R14B03 sí se puede

http://stackoverflow.com/questions/7854270/erlang-simple-one-for-one-supervisor-terminate-child-isnt-working
y yo lo estoy haciendo y funciona bien, cómo hacian antes de R14B03
para terminar los procesos child de un supervisor simple_one_for_one?

Gracias,

Andrés

Re: [erlar] estrategia simple_one_for_one y terminate_child

From:
Manuel A. Rubio \"Bombadil\"
Date:
2012-10-24 @ 15:21
Hola Andrés,

El 2012-10-24 15:53, Andrés F Vargas escribió:
> Tengo una app, y la app representa un store de tripletas (digamosles
> registros), entonces tengo un supervisor con una estrategia
> simple_one_for_one y los workers son gen_server; tengo un módulo que
> sirve de facade y expone el API pública, las funciones en ese módulo
> lo que hacen es llamar start_child, usar el api del gen_server y 
> luego
> llaman terminate_child, el efecto es 1 proceso de gen_server por
> llamada al API publica.

si lo que buscas es generar un proceso que atienda la petición y muera, 
creo que te sobran los behaviours. En todo caso, podrías tener workers 
que fuesen gen_servers para atender las peticiones y se quedasen a la 
espera de nuevas peticiones para limitar el acceso a estos. El 
supervisor te puede servir por si alguno de ellos "muere", que el 
supervisor los pueda volver a levantar. Otro gen_server puede realizar 
la tarea de entregar un proceso del pool de conexiones al cliente... 
pero no obstante, mejor no reinventar la rueda y emplear poolboy, así te 
ahorras muchos dolores de cabeza ;-)

https://github.com/devinus/poolboy

> primera pregunta, esta eso bien? tengo dudas de si gen_server
> implicitamente crea un nuevo proceso cada vez que se usa call o cast.

No, gen_server con el start_link o start normal genera el proceso en 
ese momento. Cuando ejecutar "gen_server:call" o "gen_server:cast" estás 
enviando un mensaje a ese proceso que está levantado (y cuyo PID o Name 
le tienes que dar como primer parámetro).

> Lo que no quiero es un proceso manejando un millón de mensajes sino 
> un
> millon de procesos cada uno manejando un mensaje; ese es el
> pensamiento correcto en Erlang?

Sí, es lo correcto. Pero como he dicho antes, si quieres un proceso 
nuevo por petición es mejor que lo generes, y no tiene porqué ser un 
gen_server.

> tercera pregunta, cuando investigaba el asunto me tropecé mucha veces
> con que no se podía usar terminate_child cuando el supervisor usa
> simple_one_for_one, sin embargo desde R14B03 sí se puede
> 
> 
http://stackoverflow.com/questions/7854270/erlang-simple-one-for-one-supervisor-terminate-child-isnt-working
> y yo lo estoy haciendo y funciona bien, cómo hacian antes de R14B03
> para terminar los procesos child de un supervisor simple_one_for_one?

El supervisor es sobretodo para cuando un proceso muera, el poder 
levantarlo con un tiempo de espera, y X veces antes de "darlo por 
imposible". Se puede emplear como generador de pools, porque se 
asegurará de que cada elemento dentro del pool siga vivo. Utilizarlo 
como generador de procesos es también útil, pero hay que configurarlo de 
forma que no levante un proceso que ha terminado correctamente, o sino 
te encontrarás que cada proceso no muere cuando debe y se van quedando 
ahí (vamos, generando un leak).

Intenta algo como poolboy o incluso cowboy si trabajas vía HTTP, puede 
serte de mayor ayuda.

Un saludo.
Manuel Rubio.

Re: [erlar] estrategia simple_one_for_one y terminate_child

From:
Andrés F Vargas
Date:
2012-10-24 @ 15:51
Hola Manuel gracias por responder,

2012/10/24 Manuel A. Rubio "Bombadil" <bombadil@bosqueviejo.net>:
>
> si lo que buscas es generar un proceso que atienda la petición y muera,
> creo que te sobran los behaviours. En todo caso, podrías tener workers

:O no lo había pensado, la idea si es un proceso por petición, piense
en un motor de bases de datos al que uno puede conectarse, manipular
datos y desconectarse.

> pero no obstante, mejor no reinventar la rueda y emplear poolboy, así te
> ahorras muchos dolores de cabeza ;-)
>
> https://github.com/devinus/poolboy

Gracias !

> Intenta algo como poolboy o incluso cowboy si trabajas vía HTTP, puede
> serte de mayor ayuda.

Bueno si pienso crear una interface web, pero pensaba dejar el motor
como una aplicación independiente.

gracias de nuevo!

Andrés