锋盈数科-知识库 Logo
首页
软件开发
计算机基础
Hello Halo
新手必读
关于本知识库
登录 →
锋盈数科-知识库 Logo
首页 软件开发 计算机基础 Hello Halo 新手必读 关于本知识库
登录
  1. 首页
  2. 默认分类
  3. 池式结构-连接池

池式结构-连接池

0
  • 默认分类
  • 发布于 2024-09-23
  • 0 次阅读
黄健
黄健

分布式协调系统如zookeeper、etcd,客户端都是使用一个长连接。记得之前使用k8s客户端(核心是etcd)时候,需要自己实现close()接口,我在close接口里判断如果连接断了,就重新连接。zookeeper的客户端实现也是大同小异。

但是像数据库连接、MQ连接这种,更常见的实现方式是连接池。本文采用【情境型】逻辑结构来介绍连接池的能力和使用注意事项。

能力-为什么要使用连接池

本文开头提到zookeeper和etcd客户端使用的是单一长连接,而不是连接池。咱们举两个典型场景就能明白这些大牛设计者的苦心。

zookeeper的典型使用场景是服务治理。比如使用dubbo这种服务治理框架,全公司的服务都在向zookeeper读写数据。如果zookeeper的客户端是开放出来的连接池,那zookeeper服务端要维持的连接数就是:全公司的服务数*连接池大小。ulimit(linux系统命令用来查询文件句柄数)数很快就不够用了。

etcd的典型使用场景是k8s。k8s一般用来管理整个公司的服务器集群。同理,全公司的服务器都在向etcd读写数据。如果etcd的客户端是开放出来的连接池,那etcd服务端要维持的连接数就是:全公司的服务器数*连接池大小。ulimit数会更快不够用的。

zookeeper和etcd都是主备类服务,只有一个主服务在提供写能力,不可以横向扩容。所以这种情况下,客户端连接使用连接池,那简直就是连接上的灾难。而由于处理的发布订阅数据传输本身就很小,使用连接池简直是:琉璃瓦盖鸡窝——大材小用。

但是像数据库实例这样,使用方是固定的,很多公司的生产环境一个数据库实例是一个团队单独使用的。使用方数量固定,连接的机器几千台顶天了。而且很多业务逻辑就是CURD,面向数据库编程,传输信息量很大,就不得不使用连接池了。

数据库连接池是个相对复杂的处理,一些开源大牛也会很容易写出来bug。下面咱们通过具体情境来了解一下数据库连接池使用的要点。

情境1-druid 1.0.29版本连接失效bug

上图展示了客户端通过连接池连接服务器的过程。咱们平时使用druid连接池要配置很多的参数,这些参数一部分是控制伸缩性的参数:最小连接数、最大连接数等。另外一部分是探活参数,如:空闲连接触发检查阈值

timeBetweenEvictionRunsMillis

连接池管理的复杂,从上图可以管中窥豹-可见一斑。一个线程专门用来创建和管理连接,一个专门负责取连接。druid 1.0.29版本连接失效bug就发生在图中红框的连接是否可用部分。

DruidDataSource中有个检查连接是否有效的方法:
public void validateConnection(Connection conn) throws SQLException {    String query = this.getValidationQuery();    if (conn.isClosed()) {        throw new SQLException("validateConnection: connection closed");    } else if (this.validConnectionChecker != null) {        boolean result = true;        Exception error = null;
        try {            result = this.validConnectionChecker.isValidConnection(conn, this.validationQuery, this.validationQueryTimeout);        } catch (Exception var9) {            error = var9;        }
        if (!result) {            SQLException sqlError = error != null ? new SQLException("validateConnection false", error) : new SQLException("validateConnection false");            throw sqlError;        }    } else {        if (null != query) {            Statement stmt = null;            ResultSet rs = null;
            try {                stmt = conn.createStatement();                if (this.getValidationQueryTimeout() > 0) {                    stmt.setQueryTimeout(this.getValidationQueryTimeout());                }
                rs = stmt.executeQuery(query);                if (!rs.next()) {                    throw new SQLException("validationQuery didn't return a row");                }            } finally {                JdbcUtils.close(rs);                JdbcUtils.close(stmt);            }        }    }}

注意上面代码第6行开始有个bug,result初始为true,检查连接是否异常,抛出异常直接捕获,result还是true,意思是校验没有问题。在服务端重启等场景下,这个检查会抛出socket相关异常。实际上服务端已经断开连接了。这时不会进行连接的销毁重建。造成使用了已经断开的连接来操作数据库,导致执行失败。

这是生产环境真实发生过的案例。这个bug是个低级错误,后续版本已经修复了。建议不要用这个有坑版本。

另外,建议常常做业务开发、使用数据库连接池的朋友结合下面常用参数参考看几遍DruidDataSource的源码。以便更好的了解参数的使用。

情境2-ActiveMQ未使用连接池连挂服务端


activeMQ有个是否使用连接池的配置:

spring.activemq.pool.enabled=false

这里false代表不使用连接池,不使用连接池在activeMQ里表达的意思是:每发送一条数据创建一个连接。于是有个同学进行了这样的配置以后,服务端出现大量的time_wait。time_wait表示服务端和客户端已经在进行四次挥手断开连接中了。

keepalive探活会探测到连接不可用就会进行这个断开连接操作。断连操作有一步很耗时,就是time_wait,因为它有2MSL的等待时间。很多连接的最终释放都卡在这里了。

老连接不释放,服务器资源一直占用。新连接建立就会失败,表现出来就是服务器挂了。连接参数配置需谨慎:

#true表示使用连接池spring.activemq.pool.enabled=true#连接池最大连接数spring.activemq.pool.max-connections=5#空闲的连接过期时间,默认为30秒spring.activemq.pool.idle-timeout=30000#强制的连接过期时间,与idleTimeout的区别在于:idleTimeout是在连接空闲一段时间失效,而expiryTimeout不管当前连接的情况,只要达到指定时间就失效。默认为0,never spring.activemq.pool.expiry-timeout=0

MSL解释

最后解释一下time_wait的2MSL。MSL是什么:

MSL是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。因为tcp报文(segment)是ip数据报(datagram)的数据部分,而ip头中有一个TTL域,TTL是time to live的缩写,中文可以译为“生存时间”,这个生存时间是由源主机设置初始值但不是存的具体时间,而是存储了一个ip数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减1,当此值为0则数据报将被丢弃,同时发送ICMP报文通知源主机。RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。

    TCP的TIME_WAIT状态也称为2MSL等待状态,当TCP的一端发起主动关闭,在发出最后一个ACK包后,即发送了第四次挥手的ACK包后就进入了TIME_WAIT状态,必须在此状态上停留两倍的MSL时间,等待2MSL时间主要目的是怕最后一个ACK包对方没收到,那么对方在超时后将重发第三次挥手的FIN包,主动关闭端接到重发的FIN包后可以再发一个ACK应答包。在TIME_WAIT状态时两端的端口不能使用,要等到2MSL时间结束才可继续使用。当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。不过在实际应用中可以通过设置SO_REUSEADDR选项达到不必等待2MSL时间结束再使用此端口。

标签: #知识库 257
相关文章
最全的办公楼智能化解决方案

最全的办公楼智能化解决方案 2024-10-16 08:40

办公楼综合体智能化如何建设?有哪些系统?近几年,办公楼智能化的项目越来越多,不少项目经理都参与其它,同事办公楼综合体也是弱电系统涉及的最多的项目之一,本期我们一起来看下,最全的办公楼项目智能化设计方案。

规范标准查询、下载网站 2024-10-12 16:41

我们在工作中经常需要用到各种各样的规范标准,这里给大家介绍一些免费查询和下载规范的网站,个人亲测可用。 标准查找查新网站 工标网: http://www.csres.com/ 中国国家标准化管理委员会:http://openstd.samr.gov.cn/bzgk/gb/index 全国标准信息公共

【计算机网络】网络层协议解析 2024-10-08 11:24

网络层的两种服务 IPv4 * 分类编址 划分子网 无分类地址 IPv4地址应用 IP数据报的发送和转发过程 * 主机发送IP数据报 路由器转发IP数据报 IPv4数据报首部格式 ICMP网际控制报文协议 虚拟专用网VPN与

FFmpeg教程(超级详细版) 2024-10-08 11:24

一、参考资料 通过ffmpeg把图片转换成视频 FFmpeg命令(一)、使用filter_complex命令拼接视频 FFmpeg 视频处理入门教程给新手的 20 多个 FFmpeg 命令示例 FFmpeg命令行转码

计算机网络:物理层 —— 数据的传输方式 2024-10-08 11:24

文章目录 * 传输方式 * 串行传输 * 串行传输方式 特点 应用 并行传输 * 特点 应用 网卡的串/并转换 同步传输 * 同步时钟频率的误差问题 特点 应用<

授权码机制 V2.1 2024-10-07 10:26

大家好,我是机灵鹤。 根据读者朋友们反馈的问题和建议,对 授权码 V2.0 版本做了一些优化。 优化内容主要解决了以下几个问题: 优化了授权机制中的时间校验逻辑,避免用户通过回调本地时间来绕过授权机制的问题。 封装和简化了授权接口,开发者可以更方便地接入到自己的程序中。

目录

IT 外包服务商

  • 意见投递
  • zyf6619

软件开发应用

主菜单

  • 首页
  • 软件开发
  • 计算机基础
  • Hello Halo
  • 新手必读
  • 关于本知识库
Copyright © 2024 your company All Rights Reserved. Powered by Halo.