run rails deploy ruby-on-rails ruby concurrency puma

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 a config.allow_concurrency (Rack :: Bloqueo de solicitud de bloqueo) no config.allow_concurrency efecto, las solicitudes concurrentes están permitidas de forma predeterminada. Si tiene config.cache_classes=false , puede configurar config.allow_concurrency en true o false . 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.