连接池与不稳定网络

2012年07月21日 10:07:07

阅读数:2006

连接池技术,大大的提升了应用程序的性能,但是如果不了解连接池的使用场景和原理,就茫然使用连接池,.net默认使用连接池,大多数人会选择使用连接池的默认设置,这样带来的后果往往也是惨痛的,也许你将花费更大的代价去查找因为连接池的不当使用而带来的未知问题。

在一个项目中,因为连接池的不当使用而带来了一个惨痛的教训。一般我们的应用程序如果部署在一个较为稳定的网络环境中,默认使用连接池可能不会有什么问题,如果一旦部署到一个不稳定的网络环境,你就必须得绞尽脑汁去面对那些应用不稳定代带来的折磨。

首先,大概说一下连接池的原理

数据库连接池允许应用程序重用已存在于池中的数据库连接,以避免反复的建立新的数据库连接。这种技术能有效提高应用程序的伸缩性,因为有限的数据库连接能够给大量的客户提供服务。这种技术同时也提高的系统性能,避免了大量建立新连接的开销。

  开发一个具有伸缩性的、高性能应用程序应该最大限度的减少建立连接所花费的时间,保持数据库连接最大限度的有效,以存取数据。当一个数据库连接关闭时,它只是由连接池收回以待重用,并未真正释放。但是,如果连接池被释放,数据库连接将会被释放掉。

  开发人员应当注意不要依赖垃圾回收机制去释放数据库连接,因为当参数超出作用域时,数据库连接并没有得必要的关闭,这种数据库资源泄漏将导致建立新连接时抛出连接错误。

  建立数据库连接池

  当打开一个数据库连接时,一个数据库连接池也就创建了。数据库连接池的创建与数据库连接字符串精确的相关(包括空格、大小写)。所有的连接池是根据连接字符串来区分的。在创建一个新的数据库连接时,如果连接字符串不完全相同,将创建不同的连接池。

  一旦数据库连接池被创建,它将一直存在直到该进程结束。维护一个非活动状态的连接池几乎不需要什么系统开销。

  连接池中的数据库连接
  
  连接池根据唯一的连接字符串被创建。在连接池被创建的同时,连接池将创建最小的数据库连接,当连接不够用时,连接池将逐个添加数据库连接直到达到最大连接数,此后的连接请求将被加入请求队列里。当调用数据库连接对象的Close方法或Dispose方法时,数据库连接将被数据库连接池回收。

  当数据库连接使用完成后,要调用Close方法或Dispose方法将它返回连接池。没有显式释放的数据库连接可能会没有返回连接池。

应用程序在建立连接时,如果启用连接池,会在连接池维护一个逻辑连接和一个物理连接。

在不稳定网络环境中,如防火墙,网闸(内外网部署应用)物理隔离,在级联交换机出现在网络阻塞的情况下出现网络瞬断的概率较大

内外网系统交互,出现网络瞬断时,再建立网路连接就很容易出现ora-03113 通信通道的文件结束或ora-03114无法连接到oracle,这两个错误在网上的解释大部分都是因为网络导致。那么针对这两种错误,如果没有必要使用连接池就设置连接字符串Pooling=false,因为在使用连接池时,一旦出现网络瞬断,连接池里的连接物理连接已经中断,但逻辑连接依然存在,当下次有新的请求时,连接池就很有可能将死连接分配出去,就会出现上面的错误。如果出现ora-03114只能重新连接。

以下之前解决这个问题时的步骤,之前写的一个总结,但是最终依然没有根治,最终不使用连接池不再出现错误,

短信中心服务开发完成后,在测试经常发现一个oracle错误:ORA-03113,而且只要一发生这个错误,短信服务就不能正常提供服务。发生的这个错误还是很有规律的,就是在业务繁忙时是不会发生这个错误的,只有在服务长时间空闲时才发生(一般是超过5分钟没有操作的情况下)。开始以为是oracle会自动切断不活动的连接,但是查看oracle的session日志后,发现oracle并没有主动切断数据库连接,而且这个数据库连接是“莫名其妙”的断开的,也即不是客户端断开的(由于程序中使用了数据库连接池,连接池会每隔一定时间将不活动的连接关闭)。然后为了查看到底是什么问题,我们就在数据库端和客户端同时监视连接的情况(在数据库端监视数据库连接,在客户端监视TCP连接数,oracle使用的1521端口通信)。这时候发现了一个有趣的问题:就是当出现ORA-03113错误时,数据库端的session显示的连接很好,但是在客户端就会发现大量的僵死的TCP连接(连接未完全关闭,状态显示是CLOSING)。这时我们就猜测可能是中间的网络环境导致TCP连接非正常关闭。咨询了“网管”后,得知应用服务器和数据库服务器之间要通过网闸,但是网管说网闸不会切断连接的。经过查询资料后(请看这一篇文章:http://www.laoxiong.net/oracle_and_firewall.html),发现我们的情况和文章上的很相似,我们就怀疑网关有TCP连接拆除功能(这个需要在落实下,摸清网闸的功能和网闸到底能对网络产生多大的影响)。经过一番测试后,最中定位到网闸应该有定时拆除TCP连接的功能(因为如果业务比较频繁的话,数据库连接是畅通的,只要在业务空闲的情况下才会出现这个问题)。

问题解决思路:

第一步:我们打算先从连接池配置开始,这些僵死连接对连接池最大的影响就是使连接池认为这些连接还是畅通的,当程序打开一个连接时,连接池就会返回一个僵死连接,这时候在僵死连接上操作就会发生ORA-03113错误。我们的思路就是将连接池关闭连接的时间缩短。尽量市空闲连接在僵死前将其关闭然后重新建立连接(注意:这样会使连接池性能有所下降)。但是经测试,这个方法的效果并不是很好,因为连接僵死的时间并不固定,所以无法设置一个合适的时间让连接池关闭连接。

第二部:使用oracle DCD功能,也就是设置sqlnet.ora的sqlnet.expire_time参数,让oracle定期发送心跳包使连接保活,但是这个方法还是有一个问题的,就是应用的心跳包会超时(TCP的keepalive属性导致)。所以为了使oracle和客户端尽早发现连接断开,需要设置TCP的keepalive参数(Windows需要设置注册表,LINUX需要设置相应的配置文件),这样可以解决短连接问题(这里的短连接指程序使用的短连接,也就是在需要使用数据库时才申请连接,快速完成事务,然后关闭连接,由于使用了连接池,所以连接并没有关闭,只是归还到连接池而已)。

第三部:短连接问题解决了,但是长连接还是照样会出现ORA-03113错误(使用长连接的是oracle AQ轮询线程,该线程会不停对AQ队列进行一次出队操作,超时时间是5m,以此来从队列里获得短信数据)。经试验检测是因为在等待的这段时间内,数据库连接断开所导致。所以我们就将出队操作的时间缩短到1m,这样就是该连接一直有活动,这样就使ora-03113的错误发生概率降到了最低。

最终的解决方案:

1.       使用oracle 的DCD国内(设置sqlnet.expire_time参数),设置操作系统的keepalive参数。

2.       针对短连接和长连接分别采用不同的数据库连接池策略,短连接使用数据库连接池,并设置连接保活时间,这样可以是连接池尽可能早的发现僵死连接。对于常连接,则不使用数据库连接池,一旦发生ORA-03113错误,说明此连接已经失效,这时就关闭此连接,并申请新的连接。

3.       缩短oracle AQ的出队等待时间,这样可以是连接经常有操作。但是这样又出现了第二个问题ORA-25228错误(队列出队超时)。随意最后队列的异常处理为:ORA-03113 关闭连接,重新申请连接,ORA-25228 不进行任何操作,直接进行下一次的出队操作。

原文地址:https://www.cnblogs.com/williamjie/p/9120872.html

时间: 2024-10-20 16:33:09

连接池与不稳定网络的相关文章

Http请求连接池 - HttpClient 的 PoolingHttpClientConnectionManager

两个主机建立连接的过程是非常复杂的一个过程,涉及到多个数据包的交换,而且也非常耗时间.Http连接须要的三次握手开销非常大,这一开销对于比較小的http消息来说更大.但是假设我们直接使用已经建立好的http连接.这样花费就比較小.吞吐率更大. 传统的HttpURLConnection并不支持连接池.假设要实现连接池的机制,还须要自己来管理连接对象.对于网络请求这种底层相对复杂的操作.个人以为假设有可用的其它方案,也没有必要自己去管理连接对象. 除了HttpURLConnection,大家肯定还知

Ti:关于DB连接池

1.连接池的概念 网络编程中提出了将Socket放入池中,让多个线程共享这些插座(Socket)对应的线缆(Conenction),DB连接池就是基于连接池的一个实现. ①连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用. @百度百科 ②数据库连接池这一解决方案是指在应用程序启动时,建立足够的数据库连接,并将这些连接组成一个连接池,由应用程序动态的对池中的连接进行申请/使用/释放. 而对于多于连接池中连接数的并发请求,应在请求队列中排队等待连接的释放. 应用程序可

性能测试(九)连接池和线程

之前的博客中,有说的性能测试常见术语:连接池.其中大概简述了连接池的作用等,这篇博客,就介绍下连接池以及连接池中线程对象的原理,作用以及优点... 一.连接池 1.什么是连接池?我们为什么需要它? 连接池允许多个客户端使用缓存起来的连接对象,这些对象可以连接数据库,它们是共享的.可被重复使用的. 打开/关闭数据库连接开销很大,连接池技术允许我们在连接池里维护连接对象,这样可以提高数据库的执行命令的性能.多个客户端请求可以重复使用相同的连接对象,当每次收到一个客户端请求时, 就会搜索连接池,看看有

聊聊连接池和线程

一.连接池 1.什么是连接池?我们为什么需要它? 连接池允许多个客户端使用缓存起来的连接对象,这些对象可以连接数据库,它们是共享的.可被重复使用的. 打开/关闭数据库连接开销很大,连接池技术允许我们在连接池里维护连接对象,这样可以提高数据库的执行命令的性能.多个客户端请求可以重复使用相同的连接对象,当每次收到一个客户端请求时, 就会搜索连接池,看看有没有闲置连接对象.如果没有,要么所有的客户端请求都进入队列排队,要么在池中创建一个新的连接对象(这取决于池里已有多少个连接存在以及配置支持多少连接)

转 聊聊连接池和线程

https://www.cnblogs.com/imyalost/p/7189455.html 之前的博客中,有说到性能测试常见术语:连接池.其中大概简述了连接池的作用等,这篇博客,就介绍下连接池以及连接池中线程对象的原理,作用以及优点... 一.连接池 1.什么是连接池?我们为什么需要它? 连接池允许多个客户端使用缓存起来的连接对象,这些对象可以连接数据库,它们是共享的.可被重复使用的. 打开/关闭数据库连接开销很大,连接池技术允许我们在连接池里维护连接对象,这样可以提高数据库的执行命令的性能

JedisPool 网络连接池

首先我们如果每次使用缓存都生成一个Jedis对象的话,这样意味着会建立很多的socket连接,造成系统资源被不可控调用,甚至会导致奇怪的错误发生.如果使用单例模式,在线程安全模式下适应不了高并发的需求,非线程安全模式有可能会出现与时间相关的错误.因此,为了避免这些问题,引入了池的概念 JedisPool.JedisPool是一个线程安全的网络连接池,我们可以通过JedisPool创建和管理Jedis实例,这样可以有效地解决以上问题以实现系统的高性能. ? public class JedisPo

网络协议 finally{ return问题 注入问题 jdbc注册驱动问题 PreparedStatement 连接池目的 1.2.1DBCP连接池 C3P0连接池 MYSQL两种方式进行实物管理 JDBC事务 DBUtils事务 ThreadLocal 事务特性 并发访问 隔离级别

1.1.1 API详解:注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用 原因有2个: >导致驱动被注册2次. >强烈依赖数据库的驱动jar 解决办法: Class.forName("com.mysql.jdbc.Driver"); 1.1.2 API详解:java.sql.Statement接口: 操作sql语句,并返回相应结果 String sql = "某SQL语句&qu

集合、多线程、网络编程、JDBC、连接池、反射、综合应用

1.使用TCP连接服务器和客户端. 2.结合反射的知识.创建JDBC和连接池. 3.客户端输入信息并保存到一个对象中,发送到服务器. 4.服务器接收对象,通过JDBC存储进数据库中. 5.把服务器放到线程中,保持启动状态. 6.客户端读取数据库的数据信息,放到集合中. 7.遍历集合,输出数据库的数据. 服务器和客户端的项目结构: 服务器 客户端 实体类: package com.luo.project.pojo; import java.io.Serializable; public class

数据源与连接池的关系

今日一直在纠结数据源与连接池,这两个东西到底是什么关系呢?因为看spring中配置的明明是连接池,但是术语却叫其 数据源,而且也没有看到其配置数据源,想想肯定是有原因的,遂来总结下. 先抛开spring的配置,先来谈谈市场上常用的数据源和连接池: 数据源:JDBC数据源,JNDI数据源,ODBC数据源等(黑体比较常用): 连接池:C3P0连接池,DBCP连接池,Porxool连接池(黑体比较常用)等 那么到底他们之间是什么关系呢? 数据源是指数据的来源,比如数据库.   连接池是指这样一个"池子