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. 自己开发轻量级ORM(一)

    在开发ORM之前,先简单的介绍下ORM的基本概念. 对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的 ...

  2. Oracle_关联查询

    1. 等值连接(Equijoin).非等值连接(Non-Equijoin).外连接(Outer join):-->左外连接-->右外连接.自连接(Self join) 交叉连接(Cross ...

  3. UI进阶 XML解析适配 引入GDataXML文件时候 'libxml/tree.h'file not found 错误解决办法

    在工程的"Build Settings"页中找到"Header Search Path"项,添加"/usr/include/libxml2" ...

  4. Raspberry树莓派学习笔记2—配置RobotFramework自动化测试环境

    一般RobotFramework都是安装在Windows/Linux的PC机上,这里将简单介绍在树莓派硬件平台上配置RobotFramework的开发和运行环境. 树莓派上配置了自动化测试软件,可以考 ...

  5. Java获取http和https协议返回的json数据

    现在很多公司都是将数据返回一个json,而且很多第三方接口都是返回json数据,而且还需要使用到http协议,http协议是属于为加密的协议,而https协议需要SSL证书,https是将用户返回的信 ...

  6. Ant学习总结5(配合Ant视频8,9)

    重点: Ant的属性介绍:  <property name="build.dir" value="build"/>注意:一般对于常量都会定义成为属性 ...

  7. Ant学习总结2

    <?xml version="1.0" encoding="UTF-8"?> <project default= "compile& ...

  8. 使用scp命令,不同服务器之间拷备文件

    使用scp命令,不同服务器之间拷备文件 先将源服务器,目标服务器安装scp服务 yum -y install openssh-clients 命令格式 scp source dist usage: s ...

  9. 转:KVC与KVO机制

    由于Objective-C是基于Smalltalk进行设计的,所以它具有动态加载.动态绑定等特性.Key-value coding (KVC) 和 key-value observing (KVO) ...

  10. Keepalived + HAProxy 搭建【第一篇】HAProxy 的安装和配置

    第一步:准备 1. 操作系统 CentOS-7-x86_64-Everything-1511 2. 安装包 haproxy-1.7.2.tar.gz 第二步:安装 # tar zxvf haproxy ...