要加密用户信息并将其存储在数据库中,我的Rails应用程序使用salt
(每个用户)使用key
生成ActiveSupport::KeyGenerator
。但是,由generate_key
方法执行的默认迭代为2**16
[1]。在每次读取(用于解密)和写入(用于加密)时,使用用户的salt
执行密钥生成会使我的应用程序变慢。
我发现,如果用于密钥生成的ActiveSupport::CachingKeyGenerator
和salt
保持不变,则length
可用于缓存密钥[2]。在内部,它使用Concurrent::Map
[3]来缓存密钥。使用ActiveSupport::CachingKeyGenerator
可以提高应用程序的性能,因为它并不总是生成密钥。
这会将我的应用程序的内存使用率提高到可以使应用程序崩溃的程度吗?
参考文献:
答案 0 :(得分:0)
共享“有效的”解决方案
由于ActiveSupport::CachingKeyGenerator
使用Concurrent::Map
,我发现高速缓存键将导致与用户数量成比例的内存使用量增加(假设所有请求都以某种方式路由到同一节点)。
为解决这个问题,我写了一个类似的CachingKeyGenerator
,其中包含ActiveSupport::KeyGenerator
和ActiveSupport::Cache::MemoryStore
。
class CachingKeyGenerator
BASE = Rails.application.secrets.secret_key_base
LENGTH = ActiveSupport::MessageEncryptor.key_len
KEY_EXPIRY = 1.day
def initialize
@key_generator = ActiveSupport::KeyGenerator.new(Rails.application.secrets.secret_key_base)
@keys_cache = ActiveSupport::Cache::MemoryStore.new(expires_in: KEY_EXPIRY)
end
def generate_key(salt)
key = @keys_cache.fetch(salt)
if key.nil?
key = @key_generator.generate_key(salt, LENGTH)
@keys_cache.write(salt, key)
end
key
end
end
根据Rails文档,ActiveSupport::Cache::MemoryStore
是线程安全的,并实现了基于LRU的清除机制[1]。这应该使高速缓存的内存使用具有确定性-设置为内存存储的大小限制(默认值-32Mb,可以在初始化期间定义)。
P.S:但是要在生产环境中部署它,如果遇到任何意外问题,请在此处进行更新。
[1] http://api.rubyonrails.org/classes/ActiveSupport/Cache/MemoryStore.html