前言

首先从ado.net的连接池开始了解,数据库操作通常是 new SqlConnection()、 Open()、 使用完后 Close(),整个过程相当耗时,特别是频繁建议套字接连接的过程。ado.net 驱动已经现实了连接池管理,Open() 等于申请连接,Close() 即归还资源。

Open() 的时候有几种情况:

1、有资源直接返回;

2、无可用资源,且未超过池最大设置值时,创建资源并返回;

3、无可用资源,此时会等待设置秒数,若仍然未获取资源则报错;

连接的复用使性能成数倍提升,试想网站在某一时刻突然爆增10万次,new 10万个SqlConnection对象显然会炸掉服务,创建,connect,disconnect,disponse,显然开销很大。

虽然ado.net自带的连接池已经接近完美,但在某些场合还不够用,先来一个压力测试。

SafeObjectPool与dapper比武测试

[HttpGet("vs_gen")]
async public Task<object> vs_gen() {
var select = Tag.Select;
var count = await select.CountAsync();
var items = await select.Page(page, limit).ToListAsync(); return new { count, items };
} [HttpGet("vs_dapper")]
async public Task<object> vs_dapper() {
var conn = new SqlConnection("Data Source=.;Integrated Security=True;Initial Catalog=cms;Pooling=true;Max Pool Size=11");
conn.Open();
var count = await conn.ExecuteScalarAsync<int>("SELECT count(1) FROM[dbo].[tag] a");
//conn.Close(); //conn = new SqlConnection("Data Source=.;Integrated Security=True;Initial Catalog=cms;Pooling=true;Max Pool Size=11");
//conn.Open();
var items = await conn.QueryAsync("SELECT TOP 20 a.[id], a.[parent_id], a.[name] FROM[dbo].[tag] a");
conn.Close(); return new { count, items };
}

连接池最大分别为:10,11

使用 apache ab 命令行测试上面两个接口

ab -c 10 -n 1000 -s 6000 测试结果差不多。

-c 100 时,vs_dapper直接挂了,vs_gen没影响(使用了SafeObjectPool)

实践证明ado.net过于暴露,突然的高并发招架不住。

SafeObjectPool

它是一个对象池,可用于控制任何资源紧缺的对象,使用容器化管重复使用提升性能,有序的排队获取,使用完后归还资源。

与ado.net连接池不同的地方,SafeObjectPool 解决池用尽后,再请求不报错,进行排队等待机制,并且适用任何对象不局限于数据库连接对象。

SafeObjectPool 提供可用性检查方法,比如 redisClient 不可用时,所有Get/GetAsync都将报错,直到后台服务检查并恢复状态。

使用方法

Install-Package SafeObjectPool

var pool = new SafeObjectPool.ObjectPool<MemoryStream>(10, () => new MemoryStream(), obj => {
if (DateTime.Now.Subtract(obj.LastGetTime).TotalSeconds > 5) {
// 对象超过5秒未活动,进行操作
}
}); var obj = pool.Get(); //借
pool.Return(obj); //归还 //或者 using 自动归还
using (var obj = pool.Get()) {
}

异常

  • 同步获取资源时 pool.Get()

【连接池名称】状态不可用,等待后台检查程序恢复方可使用。

SafeObjectPool.Get 获取超时(10秒),设置 Policy.IsThrowGetTimeoutException 可以避免该异常。

  • 异步获取资源时 pool.GetAsync()

【连接池名称】状态不可用,等待后台检查程序恢复方可使用。

SafeObjectPool.GetAsync 无可用资源且队列过长,Policy.AsyncGetCapacity =10000。

  • 后台服务检查可用性时

CheckAvailable 无法获得资源,Pool: 0/10, Get Wait: 0, GetAsync Wait: 0


扩展现实

SQLServer连接池

查看源码

var pool = new System.Data.SqlClient.SqlConnectionPool("名称", connectionString, 可用时触发的委托, 不可用时触发的委托);
var conn = pool.Get(); try {
// 使用 ...
pool.Return(conn); //正常归还
} catch (Exception ex) {
pool.Return(conn, ex); //发生错误时归还
}

MySQL连接池

查看源码

var pool = new MySql.Data.MySqlClient.MySqlConnectionPool("名称", connectionString, 可用时触发的委托, 不可用时触发的委托);
var conn = pool.Get(); try {
// 使用 ...
pool.Return(conn); //正常归还
} catch (Exception ex) {
pool.Return(conn, ex); //发生错误时归还
}

PostgreSQL连接池

查看源码

var pool = new Npgsql.NpgsqlConnectionPool("名称", connectionString, 可用时触发的委托, 不可用时触发的委托);
var conn = pool.Get(); try {
// 使用 ...
pool.Return(conn); //正常归还
} catch (Exception ex) {
pool.Return(conn, ex); //发生错误时归还
}

结语

本文由 ado.net 连接池,衍生到 SafeObjectPool,基于 SafeObjectPool 现实了 SQLServer连接池、MySQL连接池、PostgreSQL连接池。还有很多连接对象,比如redis client、rpc client、各大消息队列client,都可以封装起来。

谢谢观看,支持开源思想和奉献。

SafeObjectPool github:https://github.com/2881099/SafeObjectPool

谈一谈对象池SafeObjectPool能干什么的更多相关文章

  1. C#核心基础--浅谈类和对象的概念

    浅谈类和对象的概念 一.什么是类?什么是对象? 学习一门面向对象编程语言,我们必须得知道什么是类?什么是对象? 类(Class)实际上是对某种类型的对象定义变量和方法的原型.它表示对现实生活中一类具有 ...

  2. 浅谈Java回收对象的标记和对象的二次标记过程_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 一.对象的标记 1.什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的 ...

  3. Unity3D 游戏开发构架篇 —— 动态大场景生成 = 区域加载+对象池管理

    项目做一个类似无尽模式的场景,想了一想,其实方法很简单,做一个相关的总结. 主要先谈一谈构架,后期附上代码. 一.区域加载 其实无尽场景的实现很简单,因为屏幕限制,那么不论何时何地,我们只能看到自己的 ...

  4. 谈一谈Java8的函数式编程(二) --Java8中的流

    流与集合    众所周知,日常开发与操作中涉及到集合的操作相当频繁,而java中对于集合的操作又是相当麻烦.这里你可能就有疑问了,我感觉平常开发的时候操作集合时不麻烦呀?那下面我们从一个例子说起. 计 ...

  5. Unity 游戏框架搭建 (二十) 更安全的对象池

    上篇文章介绍了,只需通过实现IObjectFactory接口和继承Pool类,就可以很方便地实现一个SimpleObjectPool.SimpleObjectPool可以满足大部分的对象池的需求.而笔 ...

  6. 谈一谈iOS事件的产生和传递

    谈一谈iOS事件的产生和传递 1.事件的产生 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中. UIApplication会从事件队列中取出最前面的事件,并将事件 ...

  7. 谈一谈并查集QAQ(上)

    最近几日理了理学过的很多oi知识...发现不知不觉就有很多的知识忘记了... 在聊聊并查集的时候顺便当作巩固吧.... 什么是并查集呢? ( Union Find Set ) 是一种用于处理分离集合的 ...

  8. 谈一谈C#的事件

    谈一谈C#的事件 C#中事件基于委托,要理解事件要先理解委托,如果觉得自己关于委托不是很了解可以看看我前面写委托的文章 事件基于委托,是一种功能受限的委托,为委托提供了一种发布/订阅机制 使用委托时, ...

  9. 设计模式之美:Object Pool(对象池)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):实现 DatabaseConnectionPool 类. 实现方式(二):使用对象构造方法和预分配方式实现 ObjectPool ...

随机推荐

  1. HTML学习笔记3:文字和段落

    ①标题标签     <h1></h1> ~ <h6></h6>分别对应字体不同的大小,数字又小到大对应字体由大到小   ②段落     <p> ...

  2. invalid bound statement (not found)

    invalid bound statement (not found) mybatis 错误: 一般是Mapepr.xml文件中文nameapce没有和mapper接口发生映射,导致mybatis绑定 ...

  3. C# 发展史

    C# 发展史 Intro 本文主要总结介绍C# 每个版本带来的不同的语言特性. C#,读作C Sharp,是微软推出的一种基于.NET平台的.面向对象的高级编程语言.是微软公司在2000年发布的一种新 ...

  4. 关于 JavaScript 中的复制数组

    之前在写扫雷的时候,因为需要用到二维数组,当时就在复制数组这里出现了问题,所以记录一下. 当我们在需要复制数组的时候一定需要注意,数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针, ...

  5. The JRE_HOME environment variable is not defined correctly

    启动Tomcat后startup.bat脚本调用了catalina.bat,然后catalina.bat调用了setclasspath.bat,setclasspath.bat的头部定义了JAVA_H ...

  6. ActiveMQ的消息持久化机制

    为了避免意外宕机以后丢失信息,需要做到重启后可以恢复消息队列,消息系统一般都会采用持久化机制. ActiveMQ的消息持久化机制有JDBC,AMQ,KahaDB和LevelDB,无论使用哪种持久化方式 ...

  7. 消息中间件activemq的使用场景介绍(结合springboot的示例)

    一.消息队列概述 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题.实现高性能,高可用,可伸缩和最终一致性架构.是大型分布式系统不可缺少的中间件. 目前在生产环境,使 ...

  8. PyCharm中设置字体大小

    1.在file(文件)里面找到setting(设置) 2. 然后再左面Editor里面找Font,再到右面Size里面设置字体大小

  9. 沉默的螺旋--digest

    孤立的恐惧对名望的追求高度的和谐和共识是大部分人的幸福感.安全感的源头公开性能让某种行为具有社会可接受性 P5谈论和沉默决定了意见气候那些被新的东方政策说服的人,感觉自己所想的都是合理的.因此他们就会 ...

  10. UDP和TCP的差异

    UDP和TCP传递数据的差异类似于电话和明信片之间的差异. TCP就像电话,必须先验证目标是否可以访问后才开始通讯. UDP就像明信片,信息量很小而且每次传递成功的可能性很高,但是不能完全保证传递成功 ...