关于连接池:基于HiKariCP组件分析连接池原理

池塘里养:Connection;一、设计与原理1、根底案例HiKariCP作为SpringBoot2框架的默认连接池,号称是跑的最快的连接池,数据库连接池与之前两篇提到的线程池和对象池,从设计的原理上都是基于池化思维,只是在实现形式上有各自的特点;首先还是看HiKariCP用法的根底案例: import com.zaxxer.hikari.HikariConfig;import com.zaxxer.hikari.HikariDataSource;import java.sql.Connection;import java.sql.ResultSet;import java.sql.Statement;public class ConPool { private static HikariConfig buildConfig (){ HikariConfig hikariConfig = new HikariConfig() ; // 根底配置 hikariConfig.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/junit_test?characterEncoding=utf8"); hikariConfig.setUsername("root"); hikariConfig.setPassword("123456"); // 连接池配置 hikariConfig.setPoolName("dev-hikari-pool"); hikariConfig.setMinimumIdle(4); hikariConfig.setMaximumPoolSize(8); hikariConfig.setIdleTimeout(600000L); return hikariConfig ; } public static void main(String[] args) throws Exception { // 构建数据源 HikariDataSource dataSource = new HikariDataSource(buildConfig()) ; // 获取连贯 Connection connection = dataSource.getConnection() ; // 申明SQL执行 Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT count(1) num FROM jt_activity") ; // 输入执行后果 if (resultSet.next()) { System.out.println("query-count-result:"+resultSet.getInt("num")); } }}2、外围相干类HikariDataSource类:会集数据源形容的相干信息,例如配置、连接池、连贯对象、状态治理等;HikariConfig类:保护数据源的配置管理,以及参数校验,例如userName、passWord、minIdle、maxPoolSize等;HikariPool类:提供对连接池与池中对象治理的外围能力,并实现池相干监控数据的查询方法;ConcurrentBag类:摈弃了惯例池中采纳的阻塞队列作为容器的形式,自定义该并发容器来存储连贯对象;PoolEntry类:拓展连贯对象的信息,例如状态、工夫等,不便容器中追踪这些实例化对象;通过对连接池中几个外围类的剖析,也能直观地领会到该源码的设计原理,与上篇总结的对象池利用有殊途同归之妙,只是不同的组件不同的开发者在实现的时候,都具备各自的形象逻辑。 ...

April 10, 2022 · 2 min · jiezi

关于连接池:为什么需要线程池什么是池化技术

在 Java 语言中,进步程序的执行效率有两种实现办法,一个是应用线程、另一个是应用线程池。而在生产环境下,咱们通常会采纳后者。为什么会这样呢?明天咱们就来聊聊线程池的长处,以及池化技术及其利用。 1.池化技术池化技术指的是提前准备一些资源,在须要时能够重复使用这些事后筹备的资源。 池化技术的长处次要有两个:提前准备和反复利用。 以 Java 语言中的对象创立为例,在对象创立时要经验以下步骤: 依据 new 标识符前面的参数,在常量池查找类的符号援用;如果没找到符号利用(类并未加载),进行类的加载、解析、初始化等;虚拟机为对象在堆中分配内存,并将调配的内存初始化为 0,针对对象头,建设相应的形容构造(耗时操作:须要查找堆中的闲暇区域,批改内存调配状态等);调用对象的初始化办法(耗时操作:用户的简单的逻辑验证等操作,如IO、数值计算是否符合规定等)。从上述的流程中能够看出,创立一个类须要经验简单且耗时的操作,因而咱们应该尽量复用已有的类,以确保程序的高效运行,当然如果可能提前创立这些类就再好不过了,而这些性能的实现依附的就是池化技术。 2.池化技术利用常见的池化技术的利用有:线程池、内存池、数据库连接池、HttpClient 连接池等,接下来,咱们别离来看。 2.1 线程池线程池的原理很简略,相似于操作系统中的缓冲区的概念。线程池中会先启动若干数量的线程,这些线程都处于睡眠状态。当客户端有一个新的申请时,就会唤醒线程池中的某一个睡眠的线程,让它来解决客户端的这个申请,当解决完这个申请之后,线程又处于睡眠的状态。 线程池能很洼地晋升程序的性能。比方有一个省级数据大集中的银行网络核心,高峰期每秒的客户端申请并发数超过 100,如果为每个客户端申请创立一个新的线程的话,那消耗的 CPU 工夫和内存都是非常惊人的,如果采纳一个领有 200 个线程的线程池,那将会节约大量的系统资源,使得更多的 CPU 工夫和内存用来解决理论的商业利用,而不是频繁的线程创立和销毁。 2.2 内存池如何更好地管理应用程序内存的应用,同时进步内存应用的频率,这是值得每一个开发人员沉思的问题。内存池(Memory Pool)就提供了一个比拟可行的解决方案。 内存池在创立的过程中,会事后调配足够大的内存,造成一个初步的内存池。而后每次用户申请内存的时候,就会返回内存池中的一块闲暇的内存,并将这块内存的标记置为已应用。当内存应用结束开释内存的时候,也不是真正地调用 free 或 delete 的过程,而是把内寄存回内存池的过程,且放回的过程要把标记置为闲暇。最初,应用程序完结就会将内存池销毁,将内存池中的每一块内存开释。 内存池的长处: 缩小内存碎片的产生,这个长处能够从创立内存池的过程中看出,当咱们在创立内存池的时候,调配的都是一块块比拟规整的内存块,缩小内存碎片的产生。进步了内存的应用频率。这个能够从分配内存和开释内存的过程中看出。每次的调配和开释并不是去调用零碎提供的函数或操作符去操作理论的内存,而是在复用内存池中的内存。内存池的毛病: 会造成内存的节约,因为要应用内存池须要在一开始调配一大块闲置的内存,而这些内存不肯定全副被用到。 2.3 数据库连接池数据库连接池的根本思维是在零碎初始化的时候将数据库连贯作为对象存储在内存中,当用户须要拜访数据库的时候,并非建设一个新的连贯,而是从连接池中取出一个已建设的闲暇连贯对象。在应用结束后,用户也不是将连贯敞开,而是将连贯放回到连接池中,以供下一个申请拜访应用,而这些连贯的建设、断开都是由连接池本身来治理的。 同时,还能够设置连接池的参数来管制连接池中的初始连接数、连贯的上上限数和每个连贯的最大应用次数、最大闲暇工夫等。当然,也能够通过连接池本身的管理机制来监督连贯的数量、应用状况等。 2.4 HttpClient连接池HttpClient 咱们常常用来进行 HTTP 服务拜访。咱们的我的项目中会有一个获取工作执行状态的性能应用 HttpClient,一秒钟申请一次,常常会呈现 Conection Reset 异样。通过剖析发现,问题是出在 HttpClient 的每次申请都会新建一个连贯,当创立连贯的频率比敞开连贯的频率大的时候,就会导致系统中产生大量处于 TIME_CLOSED 状态的连贯,这个时候应用连接池复用连贯就能解决这个问题。 3.线程池介绍线程池是线程应用的一种模式,它将线程和工作的概念分来到,应用线程来执行工作,并提供对立的线程治理和工作治理的实现办法,防止了频繁创立和销毁线程所带来的性能开销。 4.线程池长处剖析线程池相比于线程来说,它不须要频繁的创立和销毁线程,线程一旦创立之后,默认状况下就会始终放弃在线程池中,等到有工作来了,再用这些已有的线程来执行工作,如下图所示: 长处1:复用线程,升高资源耗费线程在创立时要开拓虚拟机栈、本地办法栈、程序计数器等公有线程的内存空间,而销毁时又要回收这些公有空间资源,如下图所示: 而线程池创立了线程之后就会放在线程池中,因而线程池相比于线程来说,第一个长处就是能够复用线程、减低系统资源的耗费。 长处2:进步响应速度线程池是复用已有线程来执行工作的,而线程是在有工作时才新建的,所以相比于线程来说,线程池可能更快的响应工作和执行工作。 长处3:管控线程数和工作数线程池提供了更多的治理性能,这里治理性能次要体现在以下两个方面: 管制最大并发数:线程池能够创立固定的线程数,从而防止了有限创立线程的问题。当线程创立过多时,会导致系统执行变慢,因为 CPU 核数是肯定的、能同时解决的工作数也是肯定的,而线程过多时就会造成线程歹意争抢和线程频繁切换的问题,从而导致程序执行变慢,所以适合的线程数才是高性能运行的要害。管制工作最大数:如果工作有限多,而内存又有余的状况下,就会导致程序执行报错,而线程池能够管制最大工作数,当工作超过肯定数量之后,就会采纳回绝策略来解决多出的工作,从而保障了零碎能够衰弱的运行。长处4:更多加强性能线程池相比于线程来说提供了更多的性能,比方定时执行和周期执行等性能。 总结池化技术指的是提前准备一些资源,在须要时能够重复使用这些事后筹备的资源。池化技术的长处次要有两个:提前准备和反复利用。线程池是池化技术的典型场景,线程池的长处次要有 4 点:1.复用线程,升高了资源耗费;2.进步响应速度;3.提供了治理线程数和工作数的能力;4.更多加强性能。 最初如果你感觉此文对你有一丁点帮忙,点个赞。或者能够退出我的开发交换群:1025263163互相学习,咱们会有业余的技术答疑解惑 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star:http://github.crmeb.net/u/defu不胜感激 ! ...

March 2, 2022 · 1 min · jiezi

关于连接池:mysql连接池实现

代码如下: import pymysqlimport loggingimport tracebackimport threadingif __name__ == '__main__': from config import mysql_confelse: from config.config import mysql_conffrom dbutils.pooled_db import PooledDB# MySQL连接池class MySQLPool(object): # 类变量 pool = PooledDB(creator=pymysql, **mysql_conf) print("创立数据库连接池 >>>", id(pool)) # with上下文 def __enter__(self): self.conn = self.pool.connection() self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor) # 记得return self return self def __exit__(self, exc_type, exc_val, exc_tb): # 敞开连接池 self.cursor.close() self.conn.close() # 插入或批改操作 def insert_or_update(self, sql): try: self.cursor.execute(sql) rowid = self.cursor.lastrowid self.conn.commit() return rowid except Exception as error: print(traceback.format_exc()) # 回滚 self.conn.rollback() # 简略的日志解决 print(error) # logging.error("=======ERROR=======\n%s\nsql:%s" % (error, sql)) raise # 插入或批改操作 def insert_many(self, sql, data): try: self.cursor.executemany(sql, data) self.conn.commit() return 1 except Exception as error: print(traceback.format_exc()) # 回滚 self.conn.rollback() # 简略的日志解决 print(error) # logging.error("=======ERROR=======\n%s\nsql:%s" % (error, sql)) raise # 查问操作 def query(self, sql): try: self.cursor.execute(sql) results = self.cursor.fetchall() return results except Exception as error: # 简略的日志解决 print(error) # logging.error("=======ERROR=======:\n%s\nsql:%s" % (error, sql)) raiseif __name__ == '__main__': mysql = MySQLPool()间接调用即可 ...

May 17, 2021 · 1 min · jiezi

关于连接池:SpringBoot整合HikariCP连接池

池化思维剖析池化思维是咱们我的项目开发过程中的一种十分重要的思维,如整数池,字符串池,对象池、连接池、线程池等都是池化思维的一种利用,都是通过复用对象,以缩小因创立和开释对象所带来的资源耗费,进而来晋升零碎性能。例如Integer对象的外部池利用,代码如下: package com.cy.java.pool;public class TestInteger01 { public static void main(String[] args) { Integer n1=100;//Integer.valueOf(100) 编译时优化 Integer n2=100; Integer n3=200; Integer n4=200;//池中没有则new Integer(200) System.out.println(n1==n2);//true System.out.println(n3==n4);//false } }数据库连接池简介背景剖析目开发过程中应用程序与数据库交互时,“取得连贯”或“开释连贯”是十分耗费系统资源的两个过程,频繁地进行数据库连贯的建设和敞开会极大影响零碎的性能,若多线程并发量很大,这样耗时的数据库连贯就可能让零碎变得卡顿。因为TCP连贯的创立开销非常低廉,并且数据库所能承载的TCP并发连接数也有限度,针对这种场景,数据库连接池应运而生。如下图所示: 思考:如果当初是让你去设计一个连接池,你会从什么角度进行设计?第一:物理存储构造(基于什么构造去存储数据)第二:基于什么算法从池中取连贯?第三:基于什么算法从池中移除连贯?第四:当池中没有连贯时,基于什么形式解决连贯申请?第五:池是能够共享,咱们须要思考池在拜访的时并发平安? 连接池原理剖析在零碎初始化的时候,在内存中开拓一片空间,将肯定数量的数据库连贯作为对象存储在对象池里,并对外提供数据库连贯的获取和偿还办法。用户拜访数据库时,并不是建设一个新的连贯,而是从数据库连接池中取出一个已有的闲暇连贯对象;应用结束偿还后的连贯也不会马上敞开,而是由数据库连接池对立治理回收,为下一次借用做好筹备。如果因为高并发申请导致数据库连接池中的连贯被借用结束,其余线程就会期待,直到有连贯被偿还。整个过程中,连贯并不会敞开,而是源源不断地循环应用,有借有还。数据库连接池还能够通过设置其参数来管制连接池中的初始连接数、连贯的上上限数,以及每个连贯的最大应用次数、最大闲暇工夫等,也能够通过其本身的管理机制来监督数据库连贯的数量、应用状况等。 Java中的连接池Java官网,为了在应用程序中更好的利用连接池技术,定义了一套数据源标准,例如javax.sql.DataSource接口,基于这个接口,很多团队或集体创立了不同的连接池对象。而后咱们的应用程序中通过耦合与DataSource接口,便能够不便的切换不同厂商的连接池。Java我的项目中通过连接池获取连贯的一个根本过程,如下图所示: 在上图中,用户通过DataSource对象的getConnection()办法,获取一个连贯。如果池中有连贯,则间接将连贯返回给用户。如果池中没有连贯,则会调用Dirver(驱动,由数据库厂商进行实现)对象的connect办法从数据库获取,拿到连贯当前,能够将连贯在池中放一份,而后将连贯返回给调用方。连贯需求方再次须要连贯时,能够从池中获取,用完当前再还给池对象。 数据库连接池在Java数据库相干中间件产品群中,应该算是底层最根底的一类产品,作为企业应用开发必不可少的组件,有数蠢才们为咱们奉献了一个又一个的优良产品,它们有的随时代倒退,功成身退,有的则还在一直迭代,老而弥坚,更有新生代产品,或性能无敌,或性能全面。目前市场上常见的连接池有DBCP、C3P0,DRUID,HikariCP等。SpringBoot工程下HikariCP整合测试数据初始化关上mysql控制台,而后按如下步骤执行goods.sql文件。第一步:登录mysql。 mysql –uroot –proot第二步:设置控制台编码方式。 set names utf8;第三步:执行goods.sql文件(切记不要关上文件复制到mysql客户端运行)。 source d:/goods.sql其中goods.sql文件内容如下: drop database if exists dbgoods;create database dbgoods default character set utf8;use dbgoods;create table tb_goods( id bigint primary key auto_increment, name varchar(100) not null, remark text, createdTime datetime not null)engine=InnoDB;insert into tb_goods values (null,'java','very good',now());insert into tb_goods values (null,'mysql','RDBMS',now());insert into tb_goods values (null,'Oracle','RDBMS',now());insert into tb_goods values (null,'java','very good',now());insert into tb_goods values (null,'mysql','RDBMS',now());insert into tb_goods values (null,'Oracle','RDBMS',now());insert into tb_goods values (null,'java','very good',now());创立我的项目Module并增加相干依赖第一步:基于IDEA创立我的项目Module,如图所示: ...

February 5, 2021 · 2 min · jiezi