zoukankan      html  css  js  c++  java
  • 谈一谈对象池SafeObjectPool能干什么

    前言

    首先从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

  • 相关阅读:
    frida rpc调用维护ios手机脚本
    latex表格调整行距
    latex插图自动在双栏的最top,IEEE期刊格式
    latex插图egin{minipage}强制左移hspace命令
    SYNTHIA-RAND-CITYSCAPES数据集云盘下载
    一种用于多张图片同时缩放比较细节的软件faststone
    shopxo安装插件被限制绑定账号的问题
    ShopXo框架去掉绑定商店的提示
    拓扑排序
    前缀和和差分
  • 原文地址:https://www.cnblogs.com/kellynic/p/9768452.html
Copyright © 2011-2022 走看看