Rails应用出现ActionDispatch::Cookies::CookieOverflow错误求助
问题描述
我在Stack Overflow上看过多个相关帖子,但没法套用解决方案。我的Rails应用出现ActionDispatch::Cookies::CookieOverflow错误(来自sentry.io的错误标题)。我没在应用里自定义使用Cookie,但怀疑两个点:
- 认证gem Devise在使用Cookie,但搞不清为什么会触发溢出;
- 生成PDF的wkhtml工具可能涉及Cookie,但具体情况不明确。
这个错误是客户触发的,我自己复现不了,求提供可执行的复现步骤和解决方案。
Sentry堆栈跟踪
ActionDispatch::Cookies::CookieOverflow actionpack (6.0.3.6) lib/action_dispatch/middleware/cookies.rb in commit at line 637 actionpack (6.0.3.6) lib/action_dispatch/middleware/cookies.rb in []= at line 472 actionpack (6.0.3.6) lib/action_dispatch/middleware/session/cookie_store.rb in set_cookie at line 110 rack (2.2.3) lib/rack/session/abstract/id.rb in commit_session at line 403 rack (2.2.3) lib/rack/session/abstract/id.rb in context at line 268 rack (2.2.3) lib/rack/session/abstract/id.rb in call at line 260 actionpack (6.0.3.6) lib/action_dispatch/middleware/cookies.rb in call at line 648 actionpack (6.0.3.6) lib/action_dispatch/middleware/callbacks.rb in block in call at line 27 activesupport (6.0.3.6) lib/active_support/callbacks.rb in run_callbacks at line 101 actionpack (6.0.3.6) lib/action_dispatch/middleware/callbacks.rb in call at line 26 actionpack (6.0.3.6) lib/action_dispatch/middleware/actionable_exceptions.rb in call at line 18 actionpack (6.0.3.6) lib/action_dispatch/middleware/debug_exceptions.rb in call at line 32 actionpack (6.0.3.6) lib/action_dispatch/middleware/show_exceptions.rb in call at line 33 railties (6.0.3.6) lib/rails/rack/logger.rb in call_app at line 37 railties (6.0.3.6) lib/rails/rack/logger.rb in block in call at line 26 activesupport (6.0.3.6) lib/active_support/tagged_logging.rb in block in tagged at line 80 activesupport (6.0.3.6) lib/active_support/tagged_logging.rb in tagged at line 28 activesupport (6.0.3.6) lib/active_support/tagged_logging.rb in tagged at line 80 railties (6.0.3.6) lib/rails/rack/logger.rb in call at line 26 actionpack (6.0.3.6) lib/action_dispatch/middleware/remote_ip.rb in call at line 81 actionpack (6.0.3.6) lib/action_dispatch/middleware/request_id.rb in call at line 27 rack (2.2.3) lib/rack/method_override.rb in call at line 24 rack (2.2.3) lib/rack/runtime.rb in call at line 22 activesupport (6.0.3.6) lib/active_support/cache/strategy/local_cache_middleware.rb in call at line 29 actionpack (6.0.3.6) lib/action_dispatch/middleware/executor.rb in call at line 14 rack (2.2.3) lib/rack/sendfile.rb in call at line 110 actionpack (6.0.3.6) lib/action_dispatch/middleware/host_authorization.rb in call at line 76 sentry-ruby-core (4.3.2) lib/sentry/rack/capture_exceptions.rb in block in call at line 23 sentry-ruby-core (4.3.2) lib/sentry/hub.rb in with_scope at line 52 sentry-ruby-core (4.3.2) lib/sentry-ruby.rb in with_scope at line 147 sentry-ruby-core (4.3.2) lib/sentry/rack/capture_exceptions.rb in call at line 14 railties (6.0.3.6) lib/rails/engine.rb in call at line 527 /usr/lib/ruby/vendor_ruby/phusion_passenger/rack/thread_handler_extension.rb in process_request at line 107 /usr/lib/ruby/vendor_ruby/phusion_passenger/request_handler/thread_handler.rb in accept_and_process_next_request at line 149 /usr/lib/ruby/vendor_ruby/phusion_passenger/request_handler/thread_handler.rb in main_loop at line 110 /usr/lib/ruby/vendor_ruby/phusion_passenger/request_handler.rb in block (3 levels) in start_threads at line 419 /usr/lib/ruby/vendor_ruby/phusion_passenger/utils.rb in block in create_thread_and_abort_on_exception at line 113
复现步骤
- 模拟大体积Session数据:在本地开发环境往Devise的session或Rails全局session里存大量数据(比如带复杂关联的用户模型、大段文本),然后触发PDF生成操作,确保wkhtml工具携带当前session。
- 触发Cookie上限:浏览器单条Cookie上限一般是4KB,手动构造超出该大小的session数据(比如序列化包含大量关联数据的用户对象),执行用户触发错误的相同操作路径(比如登录后生成特定PDF)。
- 多场景组合测试:登录关联数据多的用户账号,连续多次执行PDF生成操作,观察session是否被持续追加数据。
解决方案
1. 切换Session存储方式
Rails默认用CookieStore,超过4KB就会报错,换成服务器端存储:
- RedisStore:
安装依赖gem:
修改gem install redis redis-railsconfig/initializers/session_store.rb:Rails.application.config.session_store :redis_store, { servers: ["redis://localhost:6379/0/session"], expire_after: 1.day, key: "_your_app_session" } - ActiveRecordStore:
生成session表:
修改rails generate session_migration rails db:migrateconfig/initializers/session_store.rb:Rails.application.config.session_store :active_record_store, key: "_your_app_session"
2. 清理Devise Session冗余数据
- 自定义Devise的session序列化,只存必要字段:
在用户模型里添加:def serialize_into_session [id, email] # 只存ID和必要标识,不存整个用户对象 end - 检查是否有其他代码往session里写大体积数据,删掉不必要的存储内容。
3. 隔离wkhtml的Cookie使用
- 生成PDF时,避免传递完整用户session,只传必要的认证令牌:
# 生成PDF时手动构造请求,仅携带认证令牌 pdf_url = url_for(controller: "documents", action: "show", token: current_user.authentication_token) wkhtmltopdf(pdf_url, output_path) - 确保wkhtml工具不会往session里写入额外数据。
4. 监控Session大小
- 在中间件里添加session大小监控,提前预警:
# config/initializers/session_monitor.rb class SessionSizeMonitor def initialize(app) @app = app end def call(env) session = env['rack.session'] if session size = Marshal.dump(session).size Rails.logger.warn "Session size exceeds 3KB: #{size} bytes" if size > 3072 end @app.call(env) end end Rails.application.config.middleware.use SessionSizeMonitor
内容的提问来源于stack exchange,提问作者Julian
相关产品推荐
相关产品推荐

