ruby-on-rails - deploy - ruby on rails concurrency
¿Cómo puedo atender solicitudes al mismo tiempo que Rails 4? (3)
Estoy tratando de atender múltiples solicitudes al mismo tiempo en Rails 4, algo que pude hacer muy fácilmente con config.threadsafe!
y Puma
en Rails 3.
Di que tengo este controlador
class ConcurrentController < ApplicationController
def index
sleep 10000
end
def show
end
end
Solía ser capaz de simplemente iniciar puma con puma -t 2:16 -p 3000
(para min 2 hilos) y presionar index
y luego show
y aún así show
renderizado correctamente.
En Rails 4, si intento hacer lo mismo, Puma ahora bloquea la solicitud de index
y el show
nunca se procesa. Cuando presiono Ctrl-C
para el servidor Puma me da este error:
Rack app error: #<ThreadError: Attempt to unlock a mutex which is locked by another thread>
¿Qué me falta aquí para hacer que la simultaneidad funcione con Rails 4? config.threadsafe!
se supone que no es necesario (y no hace una diferencia, incluso si lo intento)
¡Te invito a leer sobre las opciones de configuración de config.threadsafe!
en este artículo Eliminando config.threadsafe! ¡Te ayudará a comprender mejor las opciones de config.threadsafe!
, en particular para permitir la concurrencia.
En Rails 4 config.threadsafe!
se establece de forma predeterminada.
Ahora a la respuesta
En Rails 4, las solicitudes se envuelven alrededor de un Mutex por el Rack :: Lock middleware en entornos DEV por defecto.
Si desea habilitar la concurrencia , puede configurar config.allow_concurrency=true
. Esto deshabilitará el middleware Rack :: Lock. No lo eliminaría como se menciona en otra respuesta a su pregunta; eso parece un truco para mí.
Nota : Si tiene
config.cache_classes=true
, la asignación aconfig.allow_concurrency
(Rack :: Bloqueo de solicitud de bloqueo) noconfig.allow_concurrency
efecto, las solicitudes concurrentes están permitidas de forma predeterminada. Si tieneconfig.cache_classes=false
, puede configurarconfig.allow_concurrency
entrue
ofalse
. En el entorno DEV querrías tenerlo así.
config.cache_classes=false config.allow_concurrency=true
La declaración: lo que significa que si config.cache_classes = false (que es por defecto en dev env) no podemos tener solicitudes simultáneas. no es correcto.
Apéndice
Puede consultar esta respuesta , que configura un experimento que prueba la concurrencia usando MRI y JRuby. Los resultados son sorprendentes. La resonancia magnética fue más rápida que JRuby.
El experimento con concurrencia MRI está en GitHub . El experimento solo prueba solicitudes concurrentes. No hay condiciones de carrera en el controlador. Sin embargo, creo que no es demasiado difícil implementar un ejemplo del artículo anterior para probar las condiciones de carrera en un controlador.
Parece que, por defecto, en Rails 4, las solicitudes simultáneas no están habilitadas en el entorno de desarrollo.
Encontré esta cita en la documentation .
Rack :: Lock ajusta la aplicación en mutex por lo que solo se puede invocar con un solo hilo a la vez. Solo está habilitado cuando config.cache_classes es falso.
Lo que significa que si config.cache_classes = false
(que es por defecto en dev env) no podemos tener solicitudes simultáneas.
Las solicitudes simultáneas funcionan con mi ejemplo en el entorno de producción.
Una solución es establecer config.cache_classes = true
en el entorno de desarrollo, pero luego el código no se vuelve a cargar en un cambio, lo que realmente no funciona para el desarrollo.
El segundo tipo de solución pirata es deshabilitar el middleware Rack::Lock
en desarrollo.
Entonces, si agregara en development.rb
la siguiente línea:
config.middleware.delete Rack::Lock
debería poder tener solicitudes simultáneas en el entorno de desarrollo con clases de caché desactivadas.
Puedes probar el unicornio, esto es muy simple en el modo de desarrollo: