2009-10-14 12 views
6

Me gustaría algunas ideas sobre si usar fork {} para 'fondo' un proceso de una aplicación de rieles es una buena idea o no ...usando Kernel # tenedor para procesos de fondo, pros? ¿contras?

Por lo que doy cuenta fork {my_method; Process # setsid} de hecho hace lo que se supone que debe hacer.

1) crea otro procesos con un PID diferente

2) no interrumpe el proceso de llamada (por ejemplo, continúa w/o esperando el tenedor para terminar)

3) ejecuta el niño hasta termina

..que es genial, pero ¿es una buena idea? ¿Qué está haciendo exactamente el tenedor? ¿Crea una instancia duplicada de mi instancia completa mestizo/pasajero en la memoria? Si es así, eso sería muy malo. O, de alguna manera lo hace sin consumir una gran franja de memoria.

Mi objetivo final era acabar con mi sistema de fondo daemon/cola a favor de que se bifurcan estos procesos (envío de correos electrónicos principalmente) - pero si esto no va a salvar la memoria, entonces es definitivamente un paso en la dirección equivocada

+0

Me quedaría con el sistema de colas. Si está utilizando un paquete bien mantenido para esto, no tendrá que preocuparse por los exploits de bombardeo de horquilla y los otros numerosos detalles necesarios para un buen sistema de cola. Esta es una instancia en la que debe tener cuidado de rodar su propio código a menos que haya una necesidad clara de hacerlo. –

+0

servidor de cola ++. Puede que desee verificar MQ (http://github.com/mdarby/mq) para la cola de correo electrónico. Lo he usado en producción durante meses sin problemas. –

Respuesta

0

La semántica de fork es copiar todo el espacio de memoria del proceso en un nuevo proceso, pero muchos (¿la mayoría?) Harán eso simplemente haciendo una copia de las tablas de memoria virtual y marcándola como copy-on-write. Eso significa que (al principio, al menos) no usa mucha más memoria física, solo lo suficiente para hacer las nuevas tablas y otras estructuras de datos por proceso.

Dicho esto, no estoy seguro de qué tan bien Ruby, RoR, etc. interactúa con el bifurcado de copiado en escritura. En particular, la recolección de basura podría ser problemática si toca muchas páginas de memoria (lo que hace que se copien).

+0

He escuchado ambas cosas sobre VACA ... bastante seguro de que algunos de la rama 1.8 no lo soportaron, pero REE lo hace (?). Y ambos hemos escuchado que 1.9 sí lo hace y no es compatible con COW. Dicho esto, * incluso si *, imaginar mi acción rieles: def foo do_stuff fork_and_send_email do_more_stuff final incluso si la vaca tenedor sería no la ubicación de memoria original puede cambiar al instante (por lo viene después) y así instigar una copia? Incluso si el tenedor fue la última llamada al método. Me imagino que los rieles todavía hacen cosas después de eso, por no mencionar ... la siguiente solicitud entra en el mismo proceso. jsharpe

+0

maldita sea, comentando el formateo: def foo; hacer cosas; fork_and_send_email; do_more_stuff; end – jsharpe

+0

Bueno, sí, podría ocurrir algo de copia, pero con suerte no sería todo el espacio de memoria del proceso; más bien sería páginas de memoria individuales aquí y allá (en las páginas de memoria x86 usualmente son 4 kilobytes). – wdebeaum

4

La horquilla realiza una copia de todo su proceso y, dependiendo de cómo esté conectado exactamente al servidor de la aplicación, una copia de eso también. Como se señaló en la otra discusión, esto se hace con copy-on-write, por lo que es tolerable. Unix está construido alrededor de la horquilla (2), después de todo, por lo que debe administrarlo bastante rápido. Tenga en cuenta que también se copian las E/S parcialmente almacenadas en búfer, los archivos abiertos y muchas otras cosas, así como también el estado del programa que está cargado por resorte para escribirlos, lo cual sería incorrecto.

tengo algunas ideas:

  • ¿Está utilizando Acción Mailer? Parece que el correo electrónico se haría fácilmente con AM o al Process.popen de algo. (Popen hará un fork, pero es seguido inmediatamente por un ejecutivo.)
  • elimine inmediatamente todo ese estado ejecutando Process.exec de otro intérprete de ruby ​​más su funcionalidad. Si hay demasiado estado para transferir o realmente necesita usar esos descriptores de archivos duplicados, puede hacer algo como IO#popen para que pueda enviar el trabajo del subproceso. El sistema compartirá automáticamente las páginas que contienen el texto del intérprete Ruby del subproceso.
  • Además de lo anterior, es posible que desee considerar el uso de la gema daemons. Si bien el proceso de los rieles ya es un daemon, usar la gema podría facilitar el funcionamiento de una tarea en segundo plano como servidor de trabajo por lotes y facilitar el inicio, el control, el reinicio si se produce una explosión y el cierre cuando lo haga. .
  • si lo hace salir de un subproceso fork(2) ed, utilizar en lugar de exit!exit
  • tener una cola de mensajes y un demonio ya se estableció, como lo hace, un poco suena como una buena solución para mí :-)
1

Tenga en cuenta que le impedirá usar JRuby on Rails ya que fork() no está implementado (todavía).

Cuestiones relacionadas