如何拥有线程安全的 Rails 初始化程序?
How to have thread-safe Rails initializers?
我正在考虑在我的应用程序负载较大时将我的 Rails 应用程序切换到 Sidekiq 和 Puma。但是,他们要求应用程序是线程安全的。
通常被认为不是线程安全的事物之一是全局变量。但是我的应用程序使用了 Rails 应用程序和教程中的常见模式,您可以在其中像这样在初始化程序中定义全局变量:
# config/initializers/aws.rb
...
$s3_bucket = Aws::S3::Resource.new.bucket(ENV['AWS_S3_BUCKET'])
# config/initializers/mixpanel.rb
$mixpanel = Mixpanel::Tracker.new(ENV['MIXPANEL_TOKEN']) do |*message|
...
end
# config/initializers/redis.rb
$redis = Redis.new(host: ENV['REDIS_HOST'], port: ENV['REDIS_PORT'])
# config/initializers/twilio.rb
$twilio_client = Twilio::REST::Client.new(ENV['TWILIO_ACCOUNT_SID'], ENV['TWILIO_AUTH_TOKEN'])
我喜欢这种方法,因为代码库的其余部分可以很容易地使用这些变量,而且它更简洁。
但是这些全局变量是线程安全的吗?如果没有,我有什么选择?我最好使用一种仍然使代码库易于阅读的解决方案。
在创建其他线程之前,初始化程序在主线程中 运行。它们可以是 thread-unsafe.
更好的解决方案是在每次使用它们之前实例化 mixpanel/twilio_client/etc,或者使用连接池。
我正在考虑在我的应用程序负载较大时将我的 Rails 应用程序切换到 Sidekiq 和 Puma。但是,他们要求应用程序是线程安全的。
通常被认为不是线程安全的事物之一是全局变量。但是我的应用程序使用了 Rails 应用程序和教程中的常见模式,您可以在其中像这样在初始化程序中定义全局变量:
# config/initializers/aws.rb
...
$s3_bucket = Aws::S3::Resource.new.bucket(ENV['AWS_S3_BUCKET'])
# config/initializers/mixpanel.rb
$mixpanel = Mixpanel::Tracker.new(ENV['MIXPANEL_TOKEN']) do |*message|
...
end
# config/initializers/redis.rb
$redis = Redis.new(host: ENV['REDIS_HOST'], port: ENV['REDIS_PORT'])
# config/initializers/twilio.rb
$twilio_client = Twilio::REST::Client.new(ENV['TWILIO_ACCOUNT_SID'], ENV['TWILIO_AUTH_TOKEN'])
我喜欢这种方法,因为代码库的其余部分可以很容易地使用这些变量,而且它更简洁。
但是这些全局变量是线程安全的吗?如果没有,我有什么选择?我最好使用一种仍然使代码库易于阅读的解决方案。
在创建其他线程之前,初始化程序在主线程中 运行。它们可以是 thread-unsafe.
更好的解决方案是在每次使用它们之前实例化 mixpanel/twilio_client/etc,或者使用连接池。