前言:前两篇文章.net core+Redis+IIS+nginx实现Session共享中,介绍了使用Microsoft.Extensions.Caching.Redis实现Session共享的方法,但是高并发时会有连接Redis出现Timeout的问题,这篇文章将介绍该问题的解决方案。

1、环境及工具准备

操作系统:windows10

数据库:Redis

压力测试工具:JMeter(传送门

2、背景介绍

项目迁移到.net core并上线以后,运行没多久接口就频繁罢工,容器没有挂,redis、mogodb、sql server全都正常,容器重启后可以正常一下,但是没过多久就又罢工了,最后只有通过docker logs命令挨个去寻找容器日志中记录的错误信息,结果发现了StackExchange.Redis.RedisTimeoutException: Timeout performing EVAL。这里说明下是.net core2.2版本,不知道3.1版本还会不会有这个问题。

3、问题重现

打开JMeter压力测试工具 ,添加一个http请求

使用上篇文章发布在docker的地址和请求参数

设置线程数为500,循环次数为3,并运行,从汇总报告中可以看出,错误率高达50%以上

使用docker logs查看容器日志,发现了同线上一样的Redis连接超时错误,且Redis数据中缓存的数量只有668(理论上应该是500*3=1500)

4、问题分析过程

(1)找到Redis组件注入的地方

(2)查看AddDistributedRedisCache源码,发现注入的是一个单例的IDistributedCache对象:

然后就发现RedisCache对象是用ConnectionMultiplexer管理Redis连接的

这里针对ConnectionMultiplexer对象做了线程安全

(3)进一步查看源码,也没有发现连接池的使用,而且从官网上的介绍来看,ConnectionMultiplexer中也没有连接池的概念,RedisCache对象中用于访问Redis数据库的私有属性_cache,并不是从连接池中获取对象,这样一来,在并发量较大的时候,会出现连接等待时间过长从而导致超时的问题,所以网上查看的类似将最小线程数设置大一些的解决方案并不可行;至于将TimeOut设置大一些,不仅不解决根本问题,还有悖于使用Redis的初衷。

5、解决方案

从第4步的分析来看,Microsoft.Extensions.Caching.Redis本身就不适合用于上篇文章介绍的Session共享方案,因为官网给出的注入对象,没有用连接池管理ConnectionMultiplexer,而ConnectionMultiplexer本身也没有池的概念。这里出两种解决方案:

(1)使用Sql Server替代Redis保存Session,这是我的一位同事找到的解决方案,并成功线上救火,这种方案代码实现简单,其它地方不需要改变。

(2)使用CSRedis组件,替代Microsoft.Extensions.Caching.Redis,具体实现方式如下:

安装nuget包

对照AddDistributedRedisCache,自定义AddDistributedCsRedisCache静态方法

public static class CsRedisTest
{
public static IServiceCollection AddDistributedCsRedisCache(this IServiceCollection services, CSRedis.CSRedisClient cSRedisClient)
{
if (services == null)
{
throw new ArgumentNullException("services");
} if (cSRedisClient == null)
{
throw new ArgumentNullException("cSRedisClient");
}
//if (setupAction == null)
//{
// throw new ArgumentNullException("setupAction");
//}
services.AddOptions();
//services.Configure(setupAction);
services.Add(ServiceDescriptor.Singleton<IDistributedCache, CsRedisCacheTest>(factory => {
return new CsRedisCacheTest(cSRedisClient);
}));
return services;
}
}

对照RedisCache类,自定义CsRedisCacheTest类,继承IDistributedCache接口,这里参考的是https://github.com/2881099/Microsoft.Extensions.Caching.CSRedis

修改Startup.cs的注册方式如下:

这里的defaultdatabase貌似只能设置为0,设置为其它值会报错,这点不如Microsoft.Extensions.Caching.Redis。

测试结果如下:

连接串poolSize为50,线程数500,循环次数3,测试通过(即Redis数据库成功缓存1500条数据,汇总报告中错误率为0)

连接串poolSize为50,线程数1000,循环次数3,测试不通过,出现超时问题,利用info clients命令查看Redis客户端连接数为51(50是应用程序的,1是我通过命令连接的)

连接串poolSize为100,线程数1000,循环数次数3,客户端连接数27,测试通过

连接串poolSize为100,线程数3000,循环数次数3,客户端连接数46,测试通过

连接串poolSize为100,线程数5000,循环数次数3,客户端连接数42,测试通过

连接串poolSize为100,线程数8000,循环数次数3,客户端连接数101,测试不通过

由此可见,不断调高线程数的情况下,应用程序还是会崩溃,但是poolSize设为100基本就够用了,假设产品用户量为100万,日活20万,最高同时在线用户3万,单服务入口最高1万访问量,上面压力测试发现是可以应对15000的同时访问量的。当然poolSize也可以设置得更高,毕竟Redis允许的最大客户端连接数是10000,在没有迹象表明poolSize设置较大值不会有任何负面作用的情况下,个人觉得不宜盲目调大。另外有兴趣的同学也可以相对的做下预警机制,比如poolSize设置了100,当Redis客户端连接数达到80时,向IT人员发送短信预警,届时可以调高poolSize值,避免系统崩溃。

6、结语

到这篇文章结束,.net core+Redis+Docker+k8s(或IIS+nginx)实现Session共享才算真正完结,建议这篇文章跟前两篇文章一起看,Redis连接超时的坑,算是最大的坑之一,所以前后花了这么多篇幅介绍,如果文章中哪些错误或值得改进的地方,也欢迎大家指出。

参考资料:

1、CSRedisCache实现:  https://github.com/2881099/Microsoft.Extensions.Caching.CSRedis/blob/master/CSRedisCache.cs

2、Jemeter使用:https://www.cnblogs.com/monjeo/p/9330464.html

3、StackExchange.Redis官方介绍: https://stackexchange.github.io/StackExchange.Redis/PipelinesMultiplexers

.Net Core Web Api实践(四)填坑连接Redis时Timeout performing EVAL的更多相关文章

  1. .Net Core Web Api实践之中间件的使用(一)

    前言:从2019年年中入坑.net core已半年有余,总体上来说虽然感觉坑多,但是用起来还是比较香的.本来我是不怎么喜欢写这类实践分享或填坑记录的博客的,因为初步实践坑多,文章肯定也会有各种错误,跟 ...

  2. .Net Core Web Api实践(三).net core+Redis+docker实现Session共享

    前言:上篇文章介绍了.net core+Redis+IIS+nginx实现Session共享,本来打算直接说明后续填坑过程,但毕竟好多坑是用docker部署后出现的,原计划简单提一下.net core ...

  3. .Net Core Web Api实践(二).net core+Redis+IIS+nginx实现Session共享

    前言:虽说公司app后端使用的是.net core+Redis+docker+k8s部署的,但是微信公众号后端使用的是IIS部署的,虽说公众号并发量不大,但领导还是使用了负载均衡,所以在介绍docke ...

  4. .net core web api + Autofac + EFCore 个人实践

    1.背景 去年时候,写过一篇<Vue2.0 + Element-UI + WebAPI实践:简易个人记账系统>,采用Asp.net Web API + Element-UI.当时主要是为了 ...

  5. 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入

    使用react全家桶制作博客后台管理系统   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...

  6. ASP.NET Core Web API 最佳实践指南

    原文地址: ASP.NET-Core-Web-API-Best-Practices-Guide 介绍 当我们编写一个项目的时候,我们的主要目标是使它能如期运行,并尽可能地满足所有用户需求. 但是,你难 ...

  7. [转]ASP.NET Core Web API 最佳实践指南

    原文地址: ASP.NET-Core-Web-API-Best-Practices-Guide 转自 介绍# 当我们编写一个项目的时候,我们的主要目标是使它能如期运行,并尽可能地满足所有用户需求. 但 ...

  8. ASP.NET Core Web API下事件驱动型架构的实现(二):事件处理器中对象生命周期的管理

    在上文中,我介绍了事件驱动型架构的一种简单的实现,并演示了一个完整的事件派发.订阅和处理的流程.这种实现太简单了,百十行代码就展示了一个基本工作原理.然而,要将这样的解决方案运用到实际生产环境,还有很 ...

  9. [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了

    [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 本文首发自:博客园 文章地址: https://www.cnblogs.com/yilezhu/p/ ...

随机推荐

  1. poj1573

    题意:给出一个矩形,N,E,S,W分别代表进行移动的方向,如果走出矩形网格则输出经过的网格数,如果在矩形网格内循环,则输出没进入循环之前所走过的网格数和循环所经过的网格数: 思路:创建两个数组,一个字 ...

  2. cfp大纲

    AFP基础知识 本章共14个考点,考试考15分左右. 本章重点: .职业道德准则 .家庭财务分析:净值的计算.储蓄的计算 .简单的财务比率分析 .金融理财和法律:企业组织形式.夫妻公共财产制度.财产分 ...

  3. linux设备驱动文件结构

    struct file, 定义于 <linux/fs.h>, 是设备驱动中第二个最重要的数据结构. 注意 file 与用户空间程序的 FILE 指针没有任何关系. 一个 FILE 定义在 ...

  4. 学习vue就是那么简单,一个简单的案例

    vue是前端兴起的一个javascript库,相信大家都使用过jQuery,虽然vue和jQuery没有可比性,但从熟悉的角度去理解新的东西或许会容易接受一些,有时候由于思想和模式的转变会带来阵痛,但 ...

  5. P1050 全排列

    题目描述 给定一个正整数n, 按照递增顺序打印数字1到n的所有排列. 输入格式 一个整数n(1<=n<=7). 输出格式 按照递增的顺序输出n的所有排列, 详见样例.请注意,每行末尾不能有 ...

  6. ajaxSetup()方法

    使用ajaxSetup()方法设置全局Ajax默认选项 使用ajaxSetup()方法可以设置Ajax请求的一些全局性选项值,设置完成后,后面的Ajax请求将不需要再添加这些选项值,它的调用格式为: ...

  7. CF526F Pudding Monsters

    CF526F Pudding Monsters 题目大意:给出一个\(n* n\)的棋盘,其中有\(n\)个格子包含棋子. 每行每列恰有一个棋子. 求\(k*k\)的恰好包含\(k\)枚棋子的子矩形个 ...

  8. VSCode提示没有权限,无法保存文件问题

    重装了系统之后,重新打开了VSCode发现无法保存修改的文件,激活系统后发现还是无法保存文件,都是提示权限问题,原因在于文件夹权限继承并不是我所登录的这个用户,接着我试着按照网上的方法,在文件夹后,右 ...

  9. supported platform

    Target name Platform Architecture Endianness Developer(s) Known Issues/Notes adm5120 Infineon/ADMtek ...

  10. linux安装python3.*,更换Python2.*

    下载并解压:Python-3.5.7.tgz [root@AH-aQYWTYSJZX01 python3]# ll total 20268 -rw-r----- 1 temp01 temp01 207 ...