前言:前两篇文章.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. P1103 走迷宫三

    题目描述 大魔王抓住了爱丽丝,将她丢进了一口枯井中,并堵住了井口. 爱丽丝在井底发现了一张地图,他发现他现在身处一个迷宫当中,从地图中可以发现,迷宫是一个N*M的矩形,爱丽丝身处迷宫的左上角,唯一的出 ...

  2. HDU 1542"Atlantis"(线段树+扫描线求矩形面积并)

    传送门 •题意 给你 n 矩形,每个矩形给出你 $(x_1,y_1),(x_2,y_2)$ 分别表示这个矩形的左下角和右上角坐标: 让你求这 n 个矩形并的面积: 其中 $x \leq 10^{5} ...

  3. java 获得Class对象

    如何得到各个字节码对应的实例对象? 每个类被加载后,系统会为该类生成对应的Class对象,通过Class对象可以访问到JVM中的这个类, 3种方式: 1.调用某个类的class属性获取Class对象, ...

  4. 关于react的redux的知识点

    项目小的时候我们getState()进行管理数据,只有当数据庞大的时候我们采用Redux来进行管理. Redux: ①:它是专注于状态管理的库,和React是解耦的 ②:它是单向数据流,单一的状态 ③ ...

  5. 微软软件开发技术二十年回顾-API篇(转)

    二. API篇 随着Windows操作系统开始占据主导地位,开发Windows平台下的应用程序成为人们的需要.当然,这也为传统的DOS程序员提供了一种新的编程方法-一种不受设备限制并由事件驱动的编程方 ...

  6. Jmeter配置元件——CSV DataSet Config参数化

    在聊CSV DataSet Config配置元件前,先来讨论下为何要参数化? 比如在做性能测试过程中, 一般我们需要模拟多个用户进行操作, 为了满足实际场景, 模拟真实的用户行为, 我们需要做到模拟的 ...

  7. 使用BFD检测EBGP邻居

    在广域网BGP环境中,通常使能BFD以快速实现链路故障后的路由的主动收敛. BFD使用UDP在链路上进行双向检测,BFD有Echo mode和asynchronous mode两种模式,默认为Echo ...

  8. java_回文检测

    package bao; import java.util.Scanner; public class Work { public static boolean digui(String str1,i ...

  9. python利用subprocess执行交互命令

    已经知道,os.system可以方便的利用python代码执行一些像ping.ipconfig之类的系统命令,但却只能得到命令执行是否成功,不能获得命令成功执行后的结果,像下面这样: >> ...

  10. $bzoj2560$ 串珠子 容斥+$dp$

    正解:容斥+$dp$ 解题报告: 传送门$QwQ$ $umm$虽然题目蛮简练的了但还是有点难理解,,,我再抽象一点儿,就说有$n$个点,点$i$和点$j$之间有$a_{i,j}$条无向边可以连,问有多 ...