Domanda Sinatra è multi thread?


Sinatra è multi-threaded? Ho letto altrove dove quel "sinatra è multi-threaded di default", che cosa implica?

Considera questo esempio

get "/multithread" do
  t1 = Thread.new{
    puts "sleeping for 10 sec"
    sleep 10
    # Actually make a call to Third party API using HTTP NET or whatever.
  }
  t1.join
  "multi thread"
end

get "/dummy" do
  "dummy"
end

Se accedo "/ multithread" e "/ dummy" successivamente in un'altra scheda o browser, nulla può essere servito (in questo caso per 10 secondi) finché la richiesta "/ multithread" non è completata. Nel caso in cui l'attività si blocca, l'applicazione non risponde.

Come possiamo aggirare questo senza generare un'altra istanza dell'applicazione?


44
2018-06-08 12:40


origine


risposte:


tl; dr Sinatra funziona bene con Threads, ma probabilmente dovrai usare un server web diverso.

Sinatra in sé non impone alcun modello di concorrenza, non gestisce nemmeno la concorrenza. Questo viene fatto dal gestore di rack (server web), come Thin, WEBrick o Passenger. Sinatra stesso è thread-safe, il che significa che se il tuo gestore Rack utilizza più thread alle richieste del server, funziona perfettamente. Tuttavia, dal momento che Ruby 1.8 supporta solo i thread verdi e Ruby 1.9 ha un blocco VM globale, i thread non sono ampiamente utilizzati per la concorrenza, poiché su entrambe le versioni, Thread non funzionerà veramente in parallelo. La volontà, tuttavia, su JRuby o sul prossimo Rubinius 2.0 (entrambe le implementazioni di Ruby alternative).

La maggior parte dei gestori di rack esistenti che utilizzano thread utilizzerà un pool di thread per riutilizzare i thread invece di creare effettivamente un thread per ogni richiesta in ingresso, poiché la creazione di thread non è gratuita, esp. su 1.9 dove i thread mappano 1: 1 ai thread nativi. I fili verdi hanno molto meno overhead, ed è per questo che le fibre, che sono fondamentalmente fili programmati in modo cooperativo, usati dalla suddetta sinatra-sincronia, sono diventate così popolari di recente. È necessario essere consapevoli che qualsiasi comunicazione di rete dovrà passare attraverso EventMachine, quindi non è possibile utilizzare il mysql gem, ad esempio, per parlare con il tuo database.

Le fibre si adattano bene all'elaborazione intensiva della rete, ma falliscono miseramente per calcoli pesanti. Hai meno probabilità di imbatterti in condizioni di competizione, una trappola comune con la concorrenza, se usi le fibre, poiché eseguono solo un cambio di contesto in punti chiaramente definiti (con sincrono, ogni volta che aspetti IO). Esiste un terzo modello di concorrenza comune: i processi. Puoi utilizzare il server di preforking o attivare autonomamente più processi. Anche se a prima vista sembra una cattiva idea, ha alcuni vantaggi: nella normale implementazione di Ruby, questo è l'unico modo per utilizzare tutte le CPU simultaneamente. E tu eviti lo stato condiviso, quindi nessuna condizione di gara per definizione. Inoltre, le app multiprocesso si adattano facilmente a più macchine. Tenere presente che è possibile combinare più processi con altri modelli di concorrenza (evented, cooperativo, preventivo).

La scelta è principalmente fatta dal server e dal middleware che usi:

  • Multiprocesso, non-preforking: Mongrel, Thin, WEBrick, Zbatery
  • Multi-Process, preforking: Unicorn, Rainbows, Passenger
  • Evented (adatto per sinatra-synchrony): Thin, Rainbows, Zbatery
  • Filettato: Net :: HTTP :: Server, Threaded Mongrel, Puma, Rainbows, Zbatery, Thin [1], Phusion Passenger Enterprise> = 4

[1] sin da Sinatra 1.3.0, Thin verrà avviato in modalità thread, se avviato da Sinatra (cioè con ruby app.rb, ma non con il thin comando, né con rackup).


91
2018-06-08 17:44



Mentre cercavi su google, ho trovato questa gemma:

Sinatra-sincronia

che potrebbe aiutarti, perché ti tocca la domanda.

C'è anche un punto di riferimento, hanno fatto quasi la stessa cosa che vuoi (chiamate esterne).

Conclusione: EventMachine è la risposta qui!


6
2018-06-08 15:41



Il pensiero che potrei elaborare per le persone che si imbattono in questo. Sinatra include questo piccolo pezzo di codice:

   server.threaded = settings.threaded if server.respond_to? :threaded=    

Sinatra rileverà quale gemma hai installato per un server web (aka, thin, puma, qualunque cosa.) E se risponde a "threaded" lo imposterà se richiesto. Neat.


4
2018-05-03 23:53



Dopo aver apportato alcune modifiche al codice, sono riuscito a eseguire l'applicazione padrino / sinatra su MIZUNO . Inizialmente ho provato a eseguire l'applicazione Padrino su jRuby ma era semplicemente troppo instabile e non ho indagato sul perché. Stavo affrontando arresti anomali di JVM durante l'esecuzione su jRuby. Ho anche passato Questo articolo, che mi fa pensare perché persino scegliere Ruby se l'implementazione può essere tutt'altro che facile.

C'è qualche discussione sulla distribuzione di applicazioni in rubino? Oppure posso generare un nuovo thread :)


1
2018-06-23 10:26



Recentemente mi sono iscritto a JRuby e sono estremamente sorpreso di quanto sia semplice passare dalla risonanza magnetica a JRuby. Si tratta in sostanza di scambiare alcune gemme (nella maggior parte dei casi).

Dovresti dare un'occhiata alla combinazione JRuby e Trinidad (App Server). Torquebox sembra anche essere un'interessante soluzione all-in-one, dotata di molto più di un semplice server di app.

Se si desidera avere un server di applicazioni che supporta il threading e si ha familiarità con Mongrel, Thin, Unicorn, ecc., Allora Trinidad è probabilmente la più facile da migrare poiché è praticamente identica dal punto di vista dell'utente. Amandolo così lontano!


1
2017-09-11 06:30