common-pool:

对于一些对象的频繁创建会带来很大的系统开销,并且需要对对象数量进行控制来降低资源消耗,比如数据库连接,线程等

common-pool采用了缓存思想来解决这个问题,预先把一些对象资源创建好并统一保存起来,也就是保存到逻辑上的对象池中

等到需要对象时从池中直接获取,不需要时归还到池中

目前对象池技术已经有很多开源优秀的库了,比如:Java实现的Apache Commons PoolGo Commons Pool

go-common-pool就是参照Apache Commons Pool的思想,用go语言实现的一个通用对象池

原理分析

几个重要的数据结构介绍

factory:

包含了一个通用对象常用的方法集合,可以理解为一个接口,client可以根据不同的对象特性自定义操作

ObjectPool:

主要包含了对象池的一些属性方法

idleObjects是一个双向队列结构,保存一些可用对象,可以用FIFO、LIFO方式访问对象

allObjectsy是一个map结构,根据key-value形式保存对象,主要用来校验对象是否存在合法

也就是说一个对象在对象池中保存两份数据,对象池会启动一个协程定时维护对象

config:

包含对象池的一些配置

初始化过程

启动一个go run去定时维护对象池中的对象集合,主要分以下几步

第一步:检查空闲对象集合剔除即将失效或者已经失效对象(通过factory.Validate()判断),不会全量检查只会检查一定数量或者比例的空闲对象(数量可配置)

第二步:遍历allObjects集合中的所有对象,剔除失效对象

第三步:判断idleObjectsCount是否大于MinIdleCount,如果小于则创建对象,并往空闲对象队列里添加节点,直到二者相等

疑问:二者是同一个分支执行过程,既然有了第一部分的检查,不知道第二步存在的意义是什么。

获取对象:BorrowObject

首先会去idleObjects队列里面获取一个对象,如果为空说明队列里面没有现成的对象,则去创建一个新的对象

在创建对象的过程中会先更新createCount,然后判断createCount是否大于MaxTotal

如果小于则继续创建对象,调用factory.Make()创建真正的对象,更新allObjects集合,如果创建成功返回新对象,如果失败返回nil

如果大于则说明对象池容量已经达到最大值,

这时候有两种选择,一种是返回错误,一种是先阻塞当前协程,等到其他协程归还对象后发送一个信号,唤醒当前协程最终获取到对象

第二种方式中支持两个设置:

一种是无限等待时间直到有错误产生,监听一种channel即可

一种是指定超时时间,超时后返回空对象和错误,需要用select监听两个channel,除了与其他协程通信channel之外,还需要一个Timer.C channel时间超时channel

伪代码可以简化为:

func takeWhithTimeout(){
  for a:=next();a==nil;a=next() {
if 没有剩余时间了
return nil
if 可以终止了
return nil
a.f()
  }
  return a
} func (a Node) f() {
  select {
    case <-a.ch: //通知channel,获取到通知说明其队列里已经有了可用对象了,同时计算一下执行当前case后还有多少时间超时
      return 剩余时间
    case <-Time.After(timeout): //时间超时channel
      return 超时了可以终止了
  }
}

  

归还对象:ReturnObject

1. 去allObjects去检查归还对象是否合法存在

2. 校验归还对象是否有效,调用factory.Validate()

3. 判断idleObjectsCount是否大于MaxIdleCount,如果小于则添加对象到idleObjects队列,否则销毁对象

总结:

go-common-pool对象池中还有很多细节没有体现出来,上面只有对整个对象池几个重要的操作进行了一个简单版的描述,后续会更新一些细节实现上的技巧

在这里我想总结下个人认为比较重要的几点

1. 一个对象的操作make(创建)-->active(激活)-->validate(校验)-->destory(销毁)-->passivate(钝化)

创建、校验操作是很容易理解也是很常用的两个操作,一般对象定义好这两个操作就可以了。

激活、钝化不容易理解,这两个操作是相对的,一个是初始化对象,一个是反初始化对象,消除之前对象占用的一些资源,

具体需要结合应用场景,不同的对象类型比如数据库连接,socket连接,线程对应不同的操作,在翻阅了一些资料后还没找到一个很好的解释。

2. poolObject是整个对象池很核心的一个对象,对外连接factory的对象操作,对内连接allObjects、idleObjects集合的操作

idleObjects/allObjects都是通过锁机制来保证线程安全操作的

几个重要事件:

一个对象加入idleObjects时需要进行(钝化)操作

一个对象在获取时需要进行(激活-->校验)操作

一个对象在归还时需要进行(校验-->钝化)操作

其中任何一步失败都需要销毁对象

3. 获取对象时支持阻塞非阻塞两种方式

go-common-pool设计原理分析的更多相关文章

  1. Terracotta设计原理分析--(部分内容来自官方描述)

    因为工作中历史产品采用了terracotta作为分布式缓存线性扩展平台,因此不得不提前对其原理做了相关了解,当然其中很多的设计思想和oracle.memcached的设计相似,但也有自己的亮点,那就是 ...

  2. kafka知识体系-kafka设计和原理分析

    kafka设计和原理分析 kafka在1.0版本以前,官方主要定义为分布式多分区多副本的消息队列,而1.0后定义为分布式流处理平台,就是说处理传递消息外,kafka还能进行流式计算,类似Strom和S ...

  3. dubbo源码解析五 --- 集群容错架构设计与原理分析

    欢迎来我的 Star Followers 后期后继续更新Dubbo别的文章 Dubbo 源码分析系列之一环境搭建 博客园 Dubbo 入门之二 --- 项目结构解析 博客园 Dubbo 源码分析系列之 ...

  4. MyBatis的深入原理分析之1-架构设计以及实例分析

    MyBatis是目前非常流行的ORM框架,它的功能很强大,然而其实现却比较简单.优雅.本文主要讲述MyBatis的架构设计思路,并且讨论MyBatis的几个核心部件,然后结合一个select查询实例, ...

  5. NOR Flash擦写和原理分析

    NOR Flash擦写和原理分析 1. NOR FLASH 的简单介绍 NOR FLASH 是很常见的一种存储芯片,数据掉电不会丢失.NOR FLASH支持Execute On Chip,即程序可以直 ...

  6. Tomcat源码分析——请求原理分析(中)

    前言 在<TOMCAT源码分析——请求原理分析(上)>一文中已经介绍了关于Tomcat7.0处理请求前作的初始化和准备工作,请读者在阅读本文前确保掌握<TOMCAT源码分析——请求原 ...

  7. Atitit.异常机制的设计原理

    Atitit.异常机制的设计原理 缺陷 关键是只要知晓有一个异常表的存在,try 的范围就是体现在异常表行记录的起点和终点.JVM 在 try 住的代码区间内如有异常抛出的话,就会在当前栈桢的异常表中 ...

  8. Spring Cloud OkHttp设计原理

    Spring Cloud 框架最底层核心的组件就是服务调用方式,一般Spring Cloud框架采用的是HTTP的调用框架,本文将在 Spring Cloud应用场景下,介绍组件OkHttp3的设计原 ...

  9. Guava Cache 原理分析与最佳实践

    前言 目前大部分互联网架构 Cache 已经成为了必可不少的一环.常用的方案有大家熟知的 NoSQL 数据库(Redis.Memcached),也有大量的进程内缓存比如 EhCache .Guava ...

随机推荐

  1. Xcode7 beta 网络请求报错:The resource could not be loaded because the App Transport

    Xcode7 beta 网络请求报错:The resource could not be loaded because the App Transport Xcode7 beta 网络请求报错:The ...

  2. Hadoop权威指南:数据完整性

    Hadoop权威指南:数据完整性 [TOC] 常用的错误检测码是CRC-32(循环冗余校验) HDFS的数据完整性 HDFS会对写入的所有数据计算校验和,并在读取数据时验证校验和 datanode负责 ...

  3. 【小梅哥FPGA进阶教程】第九章 基于串口猎人软件的串口示波器

    九.基于串口猎人软件的串口示波器 1.实验介绍 本实验,为芯航线开发板的综合实验,该实验利用芯航线开发板上的ADC.独立按键.UART等外设,搭建了一个具备丰富功能的数据采集卡,芯航线开发板负责进行数 ...

  4. 依赖lean cloud的注册与登录

    前言 实现登录注册的基本功能,没有添加手机验证和邮箱验证的功能,有相应的方法,如果需要,可以自己加上其相应的方法 github的网址: 效果图: 正文 1.导入leancloud相应的第三方,这个等我 ...

  5. Smarty3配置及入门语法

    一.Smarty3配置 下载Smarty文件 在Smarty的官方网站下载Smarty文件,解压下载到的Smarty文件,Smarty的库文件就在libs文件夹中. 我使用的PHP调试环境的程序集成包 ...

  6. Git建空白分支

    先执行以下命令从当前分支建一个分支,NEWBRANCH为新分支名字. git checkout --orphan NEWBRANCH 执行上面命令后,会切换到新分支.再执行命令下面命令,清空该分支(注 ...

  7. hive取数时如果遇到这种报错

    如果你hive取数时遇到这种报错:ParseException line 1:78 cannot recognize input near '<EOF>' '<EOF>' '& ...

  8. 用Ajax实现自动刷新news功能

    这是Ajax应用的一个小实例:在页面中自动刷新功能,比如整个新闻页面中某一个小版块的内容,无需刷新整个页面就可以自动更新: 1.首先创建简单的页面元素: <body> <input ...

  9. 深入了解Unity中LineRenderer与TrailRenderer

    LineRender和TrailRender是两个好东西,很多Unity拖尾特效都会使用到它们.一些简单的介绍可以参见官方的API文档.在这里探讨一下它们具体的渲染方式,而后给出一些Shader以便更 ...

  10. ASP.NET Core MVC之Serilog日志处理,你了解多少?

    前言 本节我们来看看ASP.NET Core MVC中比较常用的功能,对于导入和导出目前仍在探索中,项目需要自定义列合并,所以事先探索了如何在ASP.NET Core MVC进行导入.导出,更高级的内 ...