2009-09-07 20 views

Respuesta

13

Correr rake middleware en una aplicación básica rieles dicta la siguiente:

use Rack::Lock 
use ActionController::Failsafe 
use ActionController::Reloader 
use ActiveRecord::ConnectionAdapters::ConnectionManagement 
use ActiveRecord::QueryCache 
use ActiveRecord::SessionStore, #<Proc:[email protected](eval):8> 
use ActionController::RewindableInput 
use ActionController::ParamsParser 
use Rack::MethodOverride 
use Rack::Head 
run ActionController::Dispatcher.new 

El primer elemento de la pila de rack es Rack::Lock. Esto pone un candado alrededor de cada solicitud, por lo que solo se maneja una solicitud a la vez. Como tal, estándar rails es de rosca simple. Sin embargo, puede engendrar nuevos hilos dentro de una solicitud que haría que su aplicación tenga varios hilos, la mayoría de la gente nunca se encuentra con esto.

Si usted está teniendo problemas ...

require 'thread' 
Thread.exclusive do 
    # stuff here 
end 

... aseguraría que las cosas dentro del bloque no se ejecuta en paralelo con cualquier otra código.Creando un Mutext compartido entre todos los hilos (en una variable de clase o algo así, pero esto podría borrarse cuando se recarga en modo dev, así que ten cuidado), y bloquearlo como Rack::Lock#call es preferible si solo quieres asegurarte de que no haya dos instancias del mismo código se ejecuta al mismo tiempo.

Además, para el registro, cada solicitud crea y desreferencia un controlador en cada ciclo de solicitud. No hay dos solicitudes que vean la misma instancia, aunque pueden ver la misma clase.

Configuración config.threadsafe! vacíos casi todo lo que dije. Eso elimina Rack::Lock de la pila, y significa que tendrá que establecer un mutex manualmente para evitar la doble entrada. No lo hagas a menos que tengas una buena razón.

Incluso sin Rack::Lock, seguirá recibiendo una instancia de controlador por solicitud. El punto de entrada a su controlador asegura que, notice the call to new in process.

+0

Podría abordar la respuesta de cwa y esta afirmación en las preguntas frecuentes de Mongrel, "Mientras Rails se está ejecutando, solo hay un controlador en funcionamiento a la vez". ¿Qué significa eso, en funcionamiento al mismo tiempo ... que varios hilos pasan a través de una sola instancia como servlets de Java? –

+0

Por cierto, terminé sincronizándome en un semáforo Mutex por lo que mi código es seguro, sin duda, pero me gustaría entender esto de todos modos. Gracias por su respuesta ... –

+0

Rails es de rosca simple. Cada solicitud obtiene su propia instancia de controlador, y solo se maneja un hilo a la vez. – cwninja

1

Según tengo entendido, se crea una nueva instancia de controlador para cada solicitud HTTP procesada por un controlador.

+0

Correcto, eso sería exactamente como un servlet. Por lo tanto, la competencia de subprocesos podría ser un problema con los recursos de un solo subproceso. –

+0

Parece estar equivocado, John. ¿Podría verificarlo y corregir su respuesta o eliminarla, por favor? –

+0

¿Por qué escribes eso? Las variables de instancia del controlador solo existen durante el tiempo de vida de una solicitud. –

1

Ruby es de rosca simple. Entonces, en cualquier momento, un controlador solo puede manejar una solicitud a la vez. Si hay más de una solicitud, estas solicitudes se ponen en cola. Para evitar esto, las personas suelen ejecutar un pequeño conjunto de Mongrels para obtener una buena concurrencia. Funciona de esta manera (directamente desde Mongrel WIKI FAQ):

  1. Una solicitud golpea mongrel.
  2. Mestizo hace un hilo y analiza las cabeceras de petición HTTP
  3. Si el cuerpo es pequeño, entonces se pone el cuerpo en un StringIO
  4. Si el cuerpo es grande, entonces se transmite el cuerpo a un archivo temporal
  5. Cuando la solicitud está "cocinada", llame al RailsHandler.
  6. RailsHandler ve si el archivo posiblemente está en la memoria caché, si es así, envía la página almacenada en caché.
  7. Ahora, finalmente, está listo para procesar la solicitud de Rails. ¡BLOQUEAR!
  8. Aún bloqueado, Mongrel llama a Rails Dispatcher para gestionar la solicitud, pasando los encabezados y StringIO o Tempfile para el cuerpo.
  9. Cuando Rails está listo, ¡DESBLOQUEO! . Rails (con suerte) ha puesto toda su salida en un StringIO.
  10. Mongrel luego toma esta salida de StringIO, cualquier encabezado de salida, y los transmite de vuelta al cliente súper rápido.

    Observe que si no hay bloqueo, si la página está en caché.

+0

Ruby no tiene un solo subproceso. El GIL no significa que es de un solo hilo. –

Cuestiones relacionadas