2011-11-26 15 views
8

Quando arriva una nuova richiesta http, verrà avviata una nuova istanza di sinatra, ad es. sinatra deve essere inizializzato, o è solo il metodo di un'istanza precedente (il metodo get/post corrispondente di sinatra deve essere chiamato? Grazie per eventuali collegamenti alla documentazione, non sono riuscito a trovarne.Una nuova istanza di sinatra è iniziata ad ogni richiesta?

Sarebbe anche interessante se tale comportamento dipende dal tipo di distribuzione - WEBrick/etc passeggeri

+0

Ho visto molte discussioni sui modi in cui forzare Sinatra/Rack per ricaricare i file e le applicazioni di origine, quindi suppongo che non vengano ricaricati di default, ho risposto correttamente alla domanda? –

+0

Sarebbe anche molto interessante sapere se questo comportamento dipende dal tipo di distribuzione: WEBrick si comporterebbe come Passenger per uno? –

+0

@Oleg: "Ricarica un file sorgente Ruby" e "Crea una nuova istanza" sono concetti diversi. Il primo è fatto da 'require' o' load', quest'ultimo è 'TheClass.new'. – miaout17

risposta

12

Un nuovo la classe viene creata per ogni richiesta. Tuttavia, questo è non fatto da Rack. Questa è una caratteristica di Sinatra. Se vuoi approfondire i dettagli: l'istanza non viene effettivamente creata con Sinatra::Application.new ma con Sinatra::Application.prototype.dup, vedi Sinatra::Base#call per il codice.

+0

Quindi, quando non vengono gestite richieste, Rack è in attesa di richieste con un'istanza "vuota" di Sinatra caricata. Quindi, quando arriva una richiesta, Rack dice a questa istanza di duplicare e gestire la richiesta, ho capito bene? – user562529

+0

in realtà avrebbe senso aggiungere queste informazioni al sito di documentazione di sinatra –

+5

In realtà è documentato: http://www.sinatrarb.com/intro#Request/Instance%20Scope –

0

Un rapido test mostra che la stessa istanza è in esecuzione qualunque sia la richiesta (almeno, per impostazione predefinita).

require 'sinatra' 

flag = false 

get '/stuff' do 
    puts "flag is #{flag ? 'set' : 'unset'}" 
    flag = true 
end 

Quando questo codice viene eseguito e due richieste vengono ricevuti, il server richiederà flag is unset e poi flag is unset.

EDIT:

che mostra i file non vengono ricaricati. Utilizzando puts self.object_id, self.class (come consigliato da pguardiario), in realtà viene visualizzata una nuova istanza di Sinatra::Application per ogni richiesta.

+1

Questo non dimostra che si tratta di un'istanza diversa? Forse un test migliore sarebbe: mette self.object_id – pguardiario

+0

Bene, mostra che il file non è ricaricato come dice @Oleg e hai ragione: con self.object_id, vediamo che questa è una diversa istanza di Sinatra :: Application per ogni richiesta. Modificherò la mia risposta adesso. – thoferon

+0

Ancora una volta - l'esecuzione sotto il ruby ​​testfile2.rb fornisce il flag non impostato sulla prima chiamata e il flag impostato su tutte le chiamate successive. Con il fucile ottieni sempre la bandiera disinserita. Quindi affidarsi a questo tipo di comportamento per un server Web è una cattiva notizia. –

0

Esegui questo, si sa tutto, ma la dose non significare la cremagliera meccanica di correre come Sinatra. (In realtà, il rack si crea una nuova istanza per ogni richiesta)

require 'sinatra' 

configure do 
    set :number, 0 
end 

number = 0 

get '/test1' do 
    var = "The number is #{number}" 
    number = number + 1 
    var 
end 

get '/test2' do 
    var = "The number is #{settings.number}" 
    set :number, settings.number + 1 
    var 
end 
+0

eseguendo questo come file con "ruby test file.rb" e premendo test1 nel browser risulta "Il numero è 0", quindi "Il numero è 1" quindi "Il numero è 2", quindi passa a colpire test2 e inizia di nuovo a 0 e sale. –

+0

eseguendo questo file con risultati 'shotgun' in 'Il numero è 0' - sempre, non importa quello che fai. –

2

Si dovrebbe sempre presumere che l'intera app possa essere riavviata sotto le richieste intermedie. Che cosa succede se stai eseguendo 16 copie della tua app - la richiesta dell'utente 'jane' per '/' potrebbe entrare nella copia n. 2, quindi quando visita '/ signup' la richiesta colpirà # 12 (eventualmente avviato per questo evento) app. Quindi non importa ciò che fa Sinatra (anche se sembra che facciano qualcosa di simile), dal momento che la tua app potrebbe apparire ovunque, avviata oggi, ieri o un ms fa.

Se si pianifica di crescere, o di eseguire la distribuzione su Heroku, ecc., L'app deve funzionare correttamente con "shotgun", che riavvia tutto per ciascuna richiesta. Immagino che se la tua app fa qualcosa di radicalmente diverso da quello delle pagine web, e difficilmente arresti anomali o riavviati, potresti scappare con "NO"

Quindi la mia risposta è "SÌ" (ma non sempre, e nemmeno a volte generalmente).

Tuttavia, è utile sapere come funzionano le cose, in modo che si possa forse impostare solo uno schema di caching delle risorse calcolato complesso una volta per carico di app, che è un opt delle prestazioni. Ad esempio, se ogni chiamata all'app con url/calculate_pi? Decimals = 2000 risulta sempre nello stesso numero di 2000 cifre, è possibile memorizzarla in ogni istanza.

+0

grazie anche per la tua risposta pratica. Di sicuro non mi baserò per avere la stessa istanza fino in fondo. "è utile sapere come funzionano le cose" - ecco perché ho fatto questa domanda. "Quindi la mia risposta è 'SÌ' (ma non sempre, e nemmeno a volte di solito)." non è così utile capire esattamente come funziona un "ciclo di richiesta". Ci scusiamo per aver scritto male la mia domanda. – user562529

Problemi correlati