2

我已閱讀Is Rails shared-nothing or can separate requests access the same runtime variables?,他們解釋我的問題:我怎樣才能用Rails做線程安全的singleton,如何讓我的類變量安全?

類變量可能是兩個請求之間共享我的rails srver,但解決方案在哪裏!?

如何在請求之間實現安全單例?

class Foo 
    @@instances = [] 
end 

我怎樣才能確定每個請求的HTTP實例將被重置?

編輯:

我覺得「config.reload_classes_only_on_change =假」解決方案,但我不知道這是最好的性能。
這個選項有什麼後果?

我有個例來測試安全類變量:

class Test 
    def self.log 
     @test ||= false 
     puts @test 
     @test = true 
    end 
end 


class ApplicationController < ActionController::Base 
    def index 
     Test.log 
     Test.log 
    end 
end 

如果我開始這個代碼重裝行動(F5),我想在日誌中軌服務器的每一次讀「假」。但是,默認情況下,它只是第一次「假」。

編輯2: 實際上這個選項重載類,但沒有解決線程中的問題。 類變量被重置,但它們可以被其他線程修改。

線程安全類是如何變量的?

回答

5

我用的是request_store的寶石,它的效果很棒。

我的用例是爲用戶模型類添加方法,比如current_user,它們的語言環境,位置等,因爲我的其他模型經常需要這些信息。

我只是設置從我的應用程序控制器當前用戶:

User.current = the_authenticated_user 
User.request = request 

而且在我的用戶模型類:

class User 
    def self.current 
    RequestStore.store[:current_user] 
    end 

    def self.current=(user) 
    RequestStore.store[:current_user] = user 
    end 

    def self.request 
    RequestStore.store[:current_request] 
    end 

    def self.request=(request) 
    # stash the request so things like IP address and GEO-IP based location is available to other models 
    RequestStore.store[:current_request] = request 
    end 

    def self.location 
    # resolve the location just once per request 
    RequestStore.store[:current_location] ||= self.request.try(:location) 
    end 
end 

我不啓用重載類的選擇,因爲它會導致太多問題,我目睹了多個版本的課程。如果使用模型繼承(即STI),則延遲加載和/或動態類加載通常會破壞模型類的解決方式。您需要在基本和中間模型類中使用require_dependency以確保下游類也可以加載。

我的開發設置反映了我的生產設置和類處理不方便(需要服務器重啓後重啓),但比追趕不存在的錯誤更方便。 rerun gem可以監視文件系統更改併爲您重新啓動服務器,以便在開發過程中獲得可靠的更改處理,儘管比導軌破碎的類重新加載更慢。

配置/環境/ development.rb:

# Rails class reloading is broken, anytime a class references another you get multiple 
# class instances for the same named class and that breaks everything. This is especially 
# important in Sequel as models resolve classes once. 
# So always cache classes (true) 
config.cache_classes = true 

# Always eager load so that all model classes are known and STI works 
config.eager_load = true 

問:如何線程類變量?

答:沒有變量是線程安全的,除非受到synchronize的保護。

從架構角度看,Rails中的線程是浪費時間。我能夠獲得真正的並行性能/併發性的唯一方法是多個進程。它還避免了鎖定和線程相關的開銷,這些開銷在長時間運行的進程中不存在。我使用Ruby 2.x線程測試了並行CPU密集型代碼,根本沒有並行性。每個核心有1個紅寶石進程,我得到了真正的並行性。

我會認真考慮多個進程的Thin,然後決定是否要使用Thin + EventMachine來提高每個進程的整體吞吐量。

+0

我找到Thread.current的解決方案,如:http://pastebin.com/QzcpQe2h(如果我們有主控制器的uniq實例,我可以添加實例變量來存儲我的uniq數據),但是寶石更多優雅^^ thx。對於重新加載類的選項,您可以明確指出:「不啓用」<=>是否爲false? ==> config.reload_classes_only_on_change = false?那麼怎麼樣:config.cache_classes = ??? &config.eager_load = ??? – Matrix 2015-01-04 00:59:54

+0

已更新的答案。請注意,Thread.current不會在請求完成時清除線程本地存儲空間,因此如果您不小心,可能會出現狀態,資源內存和其他問題,因此建議您使用超小但實用的gem。 – 2015-01-05 09:56:53

+0

我不明白:它是線程安全的或不是?如果我們在每次請求開始時清理Thread.current中由我自己添加的所有變量(如gem do),那麼不好嗎? – Matrix 2015-01-05 10:01:38

相關問題