Redis主从架构下Microsoft.Web.SessionStateProvider执行EVAL超时排查求助
初始问题与观察
- 问题随机出现
- 读取值时提示超时
- 待排查方向:
- Redis服务是否繁忙?
- 指定的key是否缺失?
- 数据库/key是否因更新被锁定?
注:后续会持续补充观察内容协助排查。
线程池相关分析
存在两类线程池:
- 全局线程池(WorkerThreads)
- 异步读取专用线程池(IOCP)
核心逻辑:两个线程池中的繁忙线程数必须小于最小线程数,否则新线程创建会被限制500ms,进而引发超时。建议将每个CPU核心的最小线程数调至约50,并尽可能使用Redis异步API。
疑问:是否需要增加Redis Server的最小线程数?
2024-08-27 更新
- 需增加Redis客户端的最小线程数
- 问题根源在Redis客户端而非服务端
- 默认情况下,IOCP和Worker的最小线程数等于客户端所在机器的CPU核心数
- 即使服务端空闲,若客户端突增请求,线程池因未准备好处理大量请求,新线程创建(含操作系统延迟)会导致超时
- 需修改machine.config文件,添加配置:
<processModel autoConfig="false" minIoThreads="100" minWorkerThreads="100"/>
注:已在生产环境修改该设置,但问题仍存在。
线程池配置说明
- ASP.NET环境:需在machine.config的配置节点下设置
minIoThreads。该配置无法通过web.config按站点修改,会应用于所有.NET站点。注意:配置值为每核心设置,例如4核机器需将minIOThreads设为50,才能达到运行时200的效果,配置示例:
<processModel minIoThreads="50"/>
- 非ASP.NET环境:可通过以下方式配置:
- 代码调用:
ThreadPool.SetMinThreads(…) - MSBuild属性:
ThreadPoolMinThreads - runtimeconfig.json配置:
System.Threading.ThreadPool.MinThreads
- 代码调用:
2024-09-09 补充
即使将线程池最小线程数设为200,仍出现以下超时错误:
执行EVAL操作超时(5000ms),下一个操作:EVAL,实例:0,队列未处理请求数:0,队列已发送请求数:0,
异步等待:False,后台工作状态:SpinningDown,读取状态:ReadAsync,写入状态:Idle,已接收字节数:911,
上次接收字节数:0,当前接收字节数:0,同步操作数:599,异步操作数:0,服务端地址:
master.opkeyone-preprod.q1pedd.aps1.cache.amazonaws.com:6379,
连接时长:1504.86秒,异步操作计数:0,连接池状态:1/1/0,连接管理器:10个可用连接(共10个),
客户端名称:APP4(SE.Redis-v2.7.17.27058)(Microsoft.Web.RedisSessionStateProvider-v5.1.0.0),
IOCP线程池:(繁忙=6,空闲=194,最小=200,最大=200),WORKER线程池:(繁忙=9,空闲=191,最小=200,最大=200),版本:2.7.17.27058
内容的提问来源于stack exchange,提问作者Anshuman Chatterjee

