ruby-on-rails - Rails ActiveSupport::CachingKeyGenerator 的内存使用问题
问题描述
为了在数据库中加密和存储用户信息,我的 Rails 应用程序使用salt
(每个用户)生成key
using ActiveSupport::KeyGenerator
. 但是,方法执行的默认迭代generate_key
是2**16
[1]。在每次读取(用于解密)和写入(用于加密)时使用用户的密钥生成salt
会减慢我的应用程序。
我发现如果和用于密钥生成的密钥保持不变[2] ,ActiveSupport::CachingKeyGenerator
可以使用它来缓存密钥。在内部,它使用[3] 来缓存密钥。使用提高了我的应用程序的性能,因为它并不总是生成密钥。salt
length
Concurrent::Map
ActiveSupport::CachingKeyGenerator
这会将我的应用程序的内存使用量增加到可以使应用程序崩溃的水平吗?
参考:
解决方案
共享“工作”解决方案
由于ActiveSupport::CachingKeyGenerator
uses 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,可以在初始化期间定义)。
PS:尚未将其部署到生产中,如果我遇到任何意外问题,将在此处更新。
[1] http://api.rubyonrails.org/classes/ActiveSupport/Cache/MemoryStore.html
推荐阅读
- java - mvn 依赖项:resolve -Dclassifier=javadoc 在深层依赖项中的“无效模块名称”上失败。如何跳过这个问题?
- c++ - C++ 标识符未定义
- php - 想要访问网站上最新的 Instagram 订阅源,但没有收到来自 Instagram 的任何回复
- angular - 提供 Angular 组件使用的专用 api 访问时的热与冷 observables
- google-chrome-extension - 用户单击提交按钮后如何打开多个选项卡?
- synchronization - 在不同的时钟(微控制器)上同步两个 8250 uart
- django - 正常的 django_redis 会生成这种会话密钥吗?
- tensorflow - 为什么函数内部的变量没有初始化?
- python - Flask Talisman 内容安全策略
- windows - msiexec 命令行为注册表中的所有用户安装软件,而不仅仅是管理员?