ASP.Net Core使用redis连接池(StackExchange.Redis.ConnectionPool)
===============================================
2020/3/28_第1次修改 ccb_warlock
===============================================
最近有较多的时间给我做框架优化的工作,之所以会关注到redis连接池则是因为框架的数据路由层在redis连接异常时的处理有可以优化的地方,于是针对redis连接池的功能做了学习和测试。
一、价值
1.1 池子的价值
这里简单提下池子设计的价值在于当某类连接需要反复创建,且创建的开销远远大于复用的开销时,可以选择引入池子来优化这块的设计。
一般来说,池子初始化时需要限定池子的大小。
最初池子里没有一个对象,当需要对象时,从池子里获取(没有时会自动创建一个跟踪的对象后提供你使用),当对象用完后并不做真正的释放,而是将该对象放回池子里等待下一个业务需要时取用。
1.2 redis池子的价值
一般在C#的项目中主要用StackExchange.Redis作为操作redis的轮子,而StackExchange.Redis通过创建TCP连接redis后对其进行一系列操作。
既然通过tcp,我们知道需要做3次握手后才能进行后续的业务,当业务并发执行时,池子就可以更好的降低创建连接的开销,提高连接效率。
二、NuGet包
StackExchange.Redis.ConnectionPool
PS.当前使用的版本为1.0.1
三、将redis连接池引入项目
3.1 前提
我只在基于asp.net core(2.2、3.1)的项目中测试过相关功能。
3.2 添加redis的配置信息
开发过asp.net core项目的应该知道,系统提供了用appsettings.json记录配置项、并通过依赖注入在项目中获取配置信息的方案。
假设appsettings.json的内容如下:
{ "Redis": { "Host": "localhost", "Port": 6379, "Password": "123456", "PoolSize": 20 } }
3.3 创建接收配置的实体定义
public class RedisConfig { public string Host { get; set; } public int Port { get; set; } public string Password { get; set; } public int PoolSize { get; set; } }
3.4 添加连接池的依赖注入
这里先不考虑代码结构的问题,紧接着在Startup.cs中,添加下面的内容:
public class Startup { private IConfiguration Configuration { get; } public Startup(IConfiguration configuration) { Configuration = configuration; } public IServiceProvider ConfigureServices(IServiceCollection services) { //todo // 根据实际的业务量来设置最小线程数 ThreadPool.SetMinThreads(200, 200); var redisConfig = Configuration.GetSection("Redis").Get<RedisConfig>(); var redisOptions = new ConfigurationOptions { EndPoints = { {redisConfig.Host, redisConfig.Port} }, Password = redisConfig.Password, }; services.AddRedisConnectionPool(redisOptions, redisConfig.PoolSize); //todo } }
通过调用StackExchange.Redis.ConnectionPool提供的方法,就已经将redis连接池的实体注入到了整个项目中。
四、redis连接池的使用
由于我优化的框架是在数据路由层的拦截器里去使用连接池,故以此为例来做描述。
public class RouteInterceptor : BaseInterceptor { private ObjectPool<PooledConnectionMultiplexer> Pool { get; set; } public RouteInterceptor(ObjectPool<PooledConnectionMultiplexer> pool) { Pool = pool; } protected override void Handler(IInvocation invocation) { var db = 1; //todo(获取要操作的db) PooledConnectionMultiplexer client = null; try { client = Pool.GetObject(); var clientDb = redis.GetDatabase(db) //todo } catch (Exception e) { //todo } try { invocation.Proceed(); } catch (Exception e) { //todo } finally { client?.Dispose(); } } }
接着就根据StackExchange.Redis的使用方法对redis进行操作就可以了。