大家好,今天小编来为大家解答服务器连接池这个问题,什么是数据库连接池很多人还不知道,现在让我们一起来看看吧!

一、什么是数据库连接池***有什么作用

1、基本概念及原理

由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理。我们知道,对于共享资源,有一个很著名的设计模式:资源池(Resource Pool)。该模式正是为了解决资源的频繁分配?释放所造成的问题。为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量?使用情况,为系统开发?测试及*能调整提供依据。

2、服务器自带的连接池

JDBC的API中没有提供连接池的方法。一些大型的WEB应用服务器如BEA的WebLogic和IBM的WebSphere等提供了连接池的机制,但是必须有其第三方的专用类方法支持连接池的用法。

连接池关键问题分析

1、并发问题

为了使连接管理服务具有最大的通用*,必须考虑多线程环境,即并发问题。这个问题相对比较好解决,因为J*a语言自身提供了对并发管理的支持,使用synchronized关键字即可确保线程是同步的。使用方法为在类方法前面加上synchronized关键字,如:

public synchronized Connection getConnection()

2、多数据库服务器和多用户

对于大型的企业级应用,常常需要同时连接不同的数据库(如连接Oracle和Sybase)。如何连接不同的数据库呢?我们采用的策略是:设计一个符合单例模式的连接池管理类,在连接池管理类的唯一实例被创建时读取一个资源文件,其中资源文件中存放着多个数据库的url()?用户名()?密码()等信息。如 tx.url=172.21.15.123:5000/tx_it,tx.user=yang,tx.password=yang321。根据资源文件提供的信息,创建多个连接池类的实例,每一个实例都是一个特定数据库的连接池。连接池管理类实例为每个连接池实例取一个名字,通过不同的名字来管理不同的连接池。

对于同一个数据库有多个用户使用不同的名称和密码访问的情况,也可以通过资源文件处理,即在资源文件中设置多个具有相同url,但具有不同用户名和密码的数据库连接信息。

3、事务处理

我们知道,事务具有原子*,此时要求对数据库的操作符合“ALL-ALL-NOTHING”原则,即对于一组SQL语句要么全做,要么全不做。

在J*a语言中,Connection类本身提供了对事务的支持,可以通过设置Connection的AutoCommit属*为 false,然后显式的调用mit或rollback方法来实现。但要高效的进行Connection复用,就必须提供相应的事务支持机制。可采用每一个事务独占一个连接来实现,这种方法可以大大降低事务管理的复杂*。

4、连接池的分配与释放

连接池的分配与释放,对系统的*能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加快用户的访问速度。

对于连接的管理可使用空闲池。即把已经创建但尚未分配出去的连接按创建时间存放到一个空闲池中。每当用户请求一个连接时,系统首先检查空闲池内有没有空闲连接。如果有就把建立时间最长(通过容器的顺序存放实现)的那个连接分配给他(实际是先做连接是否有效的判断,如果可用就分配给用户,如不可用就把这个连接从空闲池删掉,重新检测空闲池是否还有连接);如果没有则检查当前所开连接池是否达到连接池所允许的最大连接数(maxConn),如果没有达到,就新建一个连接,如果已经达到,就等待一定的时间(timeout)。如果在等待的时间内有连接被释放出来就可以把这个连接分配给等待的用户,如果等待时间超过预定时间timeout,则返回空值(null)。系统对已经分配出去正在使用的连接只做计数,当使用完后再返还给空闲池。对于空闲连接的状态,可开辟专门的线程定时检测,这样会花费一定的系统开销,但可以保证较快的响应速度。也可采取不开辟专门线程,只是在分配前检测的方法。

5、连接池的配置与维护

连接池中到底应该放置多少连接,才能使系统的*能最佳?系统可采取设置最小连接数(minConn)和最大连接数(maxConn)来控制连接池中的连接。最小连接数是系统启动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快,响应起来却慢。这样,可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。最大连接数是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过反复测试,找到最佳点。

如何确保连接池中的最小连接数呢?有动态和静态两种策略。动态即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。

二、连接池的实现模式

1、连接池模型

本文讨论的连接池包括一个连接池类(DBConnectionPool)和一个连接池管理类(DBConionPoolManager)。连接池类是对某一数据库所有连接的“缓冲池”,主要实现以下功能:①从连接池获取或创建可用连接;②使用完毕之后,把连接返还给连接池;③在系统关闭前,断开所有连接并释放连接占用的系统资源;④还能够处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题),并能够限制连接池中的连接总数不低于某个预定值和不超过某个预定值。

连接池管理类是连接池类的外覆类(wrer),符合单例模式,即系统中只能有一个连接池管理类的实例。其主要用于对多个连接池对象的管理,具有以下功能:①装载并注册特定数据库的JDBC驱动程序;②根据属*文件给定的信息,创建连接池对象;③为方便管理多个连接池对象,为每一个连接池对象取一个名字,实现连接池名字与其实例之间的映射;④跟踪客户使用连接情况,以便需要时关闭连接释放资源。连接池管理类的引入主要是为了方便对多个连接池的使用和管理,如系统需要连接不同的数据库,或连接相同的数据库但由于安全*问题,需要不同的用户使用不同的名称和密码。

2、连接池实现

下面给出连接池类和连接池管理类的主要属*及所要实现的基本接口:

public class DBConnectionPool implements TimerListener{

private int checkedOut;//已被分配出去的连接数

private ArrayList freeConnections= new ArrayList();//容器,空闲池,根据//创建时间顺序存放已创建但尚未分配出去的连接

private int minConn;//连接池里连接的最小数量

private int maxConn;//连接池里允许存在的最大连接数

private String name;//为这个连接池取个名字,方便管理

private String password;//连接数据库时需要的密码

private String url;//所要创建连接的数据库的

private String user;//连接数据库时需要的用户名

public Timer timer;//定时器

public DBConnectionPool(String name, String URL, String user, String

password, int maxConn)//公开的构造函数

public synchronized void freeConnection(Connection con)//使用完毕之后,//把连接返还给空闲池

public synchronized Connection getConnection(long timeout)//得到一个连接,//timeout是等待时间

public synchronized void release()//断开所有连接,释放占用的系统资源

private Connection newConnection()//新建一个数据库连接

public synchronized void TimerEvent()//定时器事件处理函数

}

public class DBConnectionManager{

static private DBConnectionManager instance;//连接池管理类的唯一实例

static private int clients;//客户数量

private ArrayList drivers= new ArrayList();//容器,存放数据库驱动程序

private HashMap pools= new HashMap();//以name/value的形式存取连接池//对象的名字及连接池对象

static synchronized public DBConnectionManager getInstance()//如果唯一的//实例instance已经创建,返回这个实例;否则,调用私有构造函数,创//建连接池管理类的唯一实例

private DBConnectionManager()//私有构造函数,在其中调用初始化函数init()

public void freeConnection(String name, Connection con)//释放一个连接,//name是一个连接池对象的名字

public Connection getConnection(Stringname)//从名字为name的连接池对象//中得到一个连接

public Connection getConnection(Stringname, long time)//从名字为name

//的连接池对象中取得一个连接,time是等待时间

public synchronized void release()//释放所有资源

private void createPools(Properties props)//根据属*文件提供的信息,创建//一个或多个连接池

private void init()//初始化连接池管理类的唯一实例,由私有构造函数调用

private void loadDrivers(Properties props)//装载数据库驱动程序

}

3、连接池使用

上面所实现的连接池在程序开发时如何应用到系统中呢?下面以Servlet为例说明连接池的使用。

Servlet的生命周期是:在开始建立servlet时,调用其初始化(init)方法。之后每个用户请求都导致一个调用前面建立的实例的service方法的线程。最后,当服务器决定卸载一个servlet时,它首先调用该servlet的 destroy方法。

根据servlet的特点,我们可以在初始化函数中生成连接池管理类的唯一实例(其中包括创建一个或多个连接池)。如:

public void init() throws ServletException

{

connMgr= DBConnectionManager.getInstance();

}

然后就可以在service方法中通过连接池名称使用连接池,执行数据库操作。最后在destroy方法中释放占用的系统资源,如:

public void destroy(){

connMgr.release(); super.destroy();

}

三、你真的知道如何设置数据库连接池的大小吗

前段时间在一个老项目中经历过一个问题:一个 Dubbo服务,启动的时候慢的要死,后来看日志查原因整个过程一直在初始化数据库连接。一看数据库连接参数,连接池大小:1024。

很多入行晚的同学没有经历过手写 JDBC连接的日子。那个时候没有数据库连接池的概念,都是原生代码一顿搞,后来有了 iBATIS之后 J*a开发的繁杂程度才逐渐减轻,也衍生 C3P0数据库连接池这种基础的东西。罗马不是一天建成的,可是互联网发展太快了,技术压力逼迫下各种中间件被迫研发,大家加班加点搞出来各种高大上的脚手架,也成就很多伟人。

数据库连接使用 TCP的方式,建立连接需要3次握手,释放连接需要4次挥手,当今这种互联网使用频率下,如果每一次访问数据库都重新建立连接,我估计你们公司倒闭800次都不够。

1.数据库连接的过程是怎样的

J*a鼻祖 Sun公司是想以一套API统一天下,奈何各个数据库服务器厂商太给力统一不了。无奈之举是创建了一个统一的接口,提出一套统一接入的步骤,各个厂商实现接口,按照步骤加载自己的数据库。所以现在的方案就是4板斧:

注册驱动,为人所知的:Class.forName();

获取Connection,成功即与数据库建立连接;

拿到Statement对象,用于操作数据库的CRUD;

获取数据库返回结果ResultSet。

大家应该都知道数据库本身是一个客户端程序,只有启动了才能连接。拿 MYSQL举例,我们在安装并启动了服务的机器上,命令行的方式输入:mysql-uroot-p即可连接当前数据库。

MYSQL连接方式有很多种,区分Unix系统和 Windows系统以及通用的连接方式,在这里仅说两种方式:一种为 unix domain socket,另外一种为基于 tcp/ip协议,一般我们如果远程访问数据库肯定是基于 tcp/ip的,但是如果我们在本机登录就会分为使用 socket还是 tcp/ip。

socket:mysql-uroot-p

tcp/ip:mysql-h127.0.0.1-uroot-p

当数据库服务器和应用服务器位于不同的主机时就要使用 tcp/ip的方式建立连接。每一个连接在操作系统中占用一个线程来维护。建立连接也分为两类:短连接和长连接。

短连接

所谓短连接就是指应用程序和数据库通信完毕之后连接关闭。这种连接每次的操作就是:

发出请求--->建立连接--->操作数据--->释放连接

这样做的问题是:

频繁的建立/释放连接对数据库来说增加了系统负担;

应用程序每次操作数据库的过程将会变得很慢;

应用系统每次建立连接都要占用一个端口,频繁的建立/释放,每个被释放的连接在发出释放请求之后并不是马上就执行,必须经历一个 FIN阶段的等待直到确认为止。所以在每秒几千次数据库请求的时候,应用服务器端口很有可能被消耗完。

长连接

长连接即在建立连接后一直打开,直到应用程序关闭才释放。使用长连接的好处是减少每次创建连接带来的开销。

对于应用服务器来说维持长连接的好处不言自明,但是对于数据库服务器来说,过多的长连接则是灾难。

MYSQL的TCP连接支持长连接,所以每次操作完数据库,可以不必关掉连接,而是等待下次使用的时候在复用这个连接。所有的Socket长连接都是通过TCP自带的ping来维持心跳(TCP保活),从而保持连接状态,而我们熟悉的websocket,也正是通过TCP的心跳来维持连接不被中断。

连接池

长连接的好处这么大,自然大家都用长连接。慢慢就搞出一套长连接维护的工具-数据库连接池。

设计连接池也没有多么复杂,大致的步骤就是:

初始化连接;

业务取出连接;

业务发送请求;

放回连接。

除了上面的基本功能以外,还要处理并发问题,多数据库服务器和多用户,事务处理,连接池的配置与维护。大概就这些功能。有了连接池之后,连接的建立和释放跟业务就没有关系,交给交接池来维护。

2. MYSQL能支持多少连接

MYSQL的最大连接数在5.7版本中默认是151,最大可以达到16384(2^14)。如何设置最大连接数在于你的服务器*能,查看 MYSQL连接数信息命令如下:

mysql> show variables like'%max_connections%';

+-----------------+-------+

| Variable_name| Value|

+-----------------+-------+

| max_connections| 5050|

+-----------------+-------+

服务器连接池 什么是数据库连接池

1 row in set(0.00 sec)

我们生产环境MYSQL的最大连接数设置为 5050,注意不能设置的太小,太小造成的后果是连接失败:“query failed Error 1040: Too many connections“错误。太大且当连接该数据库的机器比较多的时候则会对当前MYSQL的*能产生影响。

MYSQL官网给出了一个设置最大连接数的建议比例:

Max_used_connections/ max_connections* 100%≈ 85%

即已使用的连接数占总上限的85%左右,如果目前已使用的连接数与最大连接数比例小于10%那很显然设置的过大。

查询当前数据库已建立连接数:

mysql> show status like'Threads_connected';

+-------------------+-------+

| Variable_name| Value|

+-------------------+-------+

| Threads_connected| 89|

+-------------------+-------+

1 row in set(0.00 sec)

Mysql的配置可以在全局变量中查询和设置,相关的配置主要可以查询下面这些:

配置

含义

Connections

尝试连接Mysql的连接数,不管连接成功与否,该值都会+1

Threads_connected

已经建立的连接数,单节点下一般小于最大连接池最大连接数

max_connections

Mysql限制的最大的可连接的数量

wait_timeout

即MYSQL长连接(非交互式)的最大生命时长,默认是8小时

interactive_timeout

长连接(交互式)的最大生命时长,默认是8小时

3.连接池设置多少连接才合适

设置连接池的大小肯定不是越大越好,需要考虑的是当前服务所在机器的*能,网络状况,数据库机器*能,数据库特*等等。同时也要做到不浪费系统资源,内存,端口,同步信号量等等。

比如说应用服务器Tomcat设置的最大线程池缺省值200,最大假设每个线程会用到一个数据库连接,那么线程池大小应该小于等于200。

另外需要考虑的是,每申请一个长连接都会在物理网络上建立一个用于长连接维护的进程,而进程的执行跟物理机的CPU核数有关。理论上一个8核的服务器将连接池设置为8最佳,每一个核同时处理一个线程,超过8的并发就有线程上下文切换的开销。

这里有一个 Oracle*能小组发布的简短视频,连接池测试分2个部分:测试视频1,测试视频2。视频中调整了线程池大小为2048的时候数据库*能陡然下降,后面调整到144就恢复了。PostgreSQL提供了一个设置预期线程池大小的公式:

connections=((core_count* 2)+ effective_spindle_count)

该公式来自于:。

其中,core_count是CPU核心, effective_spindle_count的含义是有效主轴数,如果你的服务器使用的是带有16个磁盘的RAID,那么valid_spindle_count=16。它实质上是服务器可以管理多少个并行I/ O请求的度量。旋转硬盘一次(通常)一次只能处理一个I/ O请求,如果你有16个,则系统可以同时处理16个I/ O请求。

我想 Hikari作为目前最优秀的数据库连接池之一,提出的这个公式还是经得起检验的。大家不妨在生产环境试试(出问题别找我)。

你真的知道如何设置数据库连接池的大小吗

标签:加班The带来脚手架过多功能短连接建立连接复杂