作者:京东零售董方酉
导言
运用健康度是反应运用健康程度的目标,它将体系目标分类为根底资源、容器、运用、报警装备、链路这几项,收集了一系列体系运用的目标,并对目标进行打分。
运用健康度的每一项目标显现着体系在某一方面或许存在的危险和安全问题;因而进步运用健康度关于体系监控具有重要意义。知其然需知其所以然,了解运用健康度中的目标背面的危险,关于咱们了解和进步体系安全性很有协助。
笔者作为后端研制工程师,同时在推动组内运用健康度进步的同时,依据遇到的问题现象,结合运用健康度进行分析,将逐个总结一系列运用健康度危险分析;
第一篇,咱们来分析下简单被人忽视的数据库时区设置项或许导致的危险。
一、运用健康度查看项
数据库衔接池装备中,通过解析源代码获取,支撑DBCP1.X,DBCP2.X,Ali Durid,HikariCP四种衔接池;装备监测有以下几项
危险示例如下图所示:
connectTimeout 、SocketTimeout 和 时区 三个目标是衔接池数据源的 url 中解析得到, 如:mysql://xxx.jd.com:3358/jdddddb_0?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&connectTimeout=1000&socketTimeout=3000&serverTimezone=Asia/Shanghai
其间,时区设置简单被人忽视;忽略设置会带来什么样的危险呢?
二、遇到的问题
1、现象
在2023年3月12日(3月的第二个周日),体系UMP监控报警,提示如下
2、问题原因
Mysql 驱动:mysql-connector-java 升级到8版别后。将数据库时刻解析到java时刻,需求获取数据库的时区。假如数据库衔接中指定时区,则会用该时区,不然或许会运用体系时区
可通过select @@time_zone句子查询,假如回来SYSTEM,则说明数据库没有设置时区,运用select @@system_time_zone 句子可查询得出体系默许时区,为CST。
CST时区为美国中部时刻,因为美国有夏令时和非夏令时
CST非夏令时对应 UTC-06:00,夏令时对应 UTC-05:00 。
美国的夏令时,从每年3月第2个星期天凌晨开端,到每年11月第1个星期天凌晨完毕。
以2023年为例:
夏令时开端时刻调整前:2023年03月12日周日 02:00:00,时刻向前拨一小时.
调整后:2023年03月12日周日 03:00:00
夏令时完毕时刻调整前:2023年11月05日周日 02:00:00,时刻往回拨一小时.
调整后:2023年11月05日周日 01:00:00
这意味这:CST没有2023-03-12 02:00:002023-03-12 03:00:00 这个区间的时刻。会有两个 2023-11-05 01:00:002023-11-05 02:00:00区间的时刻。
因而,在获取信息时会抛出“SQLException: HOUR_OF_DAY: 2 -> 3”反常。
3、修正计划
数据库衔接地址中设置数据时区:serverTimezone=Asia/Shanghai
三、时刻相关的其他危险
1、据研讨实验反应,设置时区为默许时或许有功能问题,往往需求指定时区。
2、运用timestamp类型时需留意时刻偏差:
timestamp类型的时刻规模between ‘1970-01-01 00:00:01’ and ‘2038-01-19 03:14:07’,超出这个规模则值记录为’0000-00-00 00:00:00’,该类型的一个重要特色就是保存的时刻与时区密切相关,UTC(Universal Time Coordinated)规范,指的是经度0度上的规范时刻,我国日常生活中时区以首都北京所处的东半球第8区为基准,统一运用东8区时刻(俗称北京时刻),比UTC要早8个小时,时区设置也遵照此规范,因而对应过来timestamp的时刻规模则应校准为’1970-01-01 08:00:01’ and ‘2038-01-19 11:14:07’,也就是说东八区的1970-1-1 08:00:01等同于UTC1970-1-1 00:00:01。
3、尽量运用dateTime格式而非timestamp:
有一些状况需求留意不要运用 timestamp 存储时刻:
• 生日:生日必定会有早于1970年的,会超出 timestamp 的规模
• 有效期截止时刻:timestamp 的最大时刻是2038年,假如用来存相似身份证的有效期截止时刻,营业执照的截止时刻等就不合适。
• 事务生存时刻:互联网时代开展快,事务时刻很或许在2038年还在继续运营。
四、数据库衔接设置的其他危险
1、衔接数设置
(1) 介绍
数据库衔接池在初始化时将创建一定数量的数据库衔接放到衔接池中,这些数据库衔接的数量是由最小数据库衔接数制约。无论这些数据库衔接是否被运用,衔接池都将一直确保至少具有这么多的衔接数量。衔接池的最大数据库衔接数量限定了这个衔接池能占有的最大衔接数,当运用程序向衔接池恳求的衔接数超越最大衔接数量时,这些恳求将被加入到等候行列中。
由此看来,当数据库最大衔接数设置不行大时,则会出现某些报表或需求查询数据库的恳求失利,因为衔接数不行不能被处理,从而报错。当出现大量并发的报表恳求,且衔接池的最大衔接数不行用时,一些用户的恳求就无法处理,这样也就从另一个层面影响了整个项目处理吞吐量的才能,约束了项目的功能和效率。
(2)设置原则
既能确保项目正常运用时对数据库衔接数的要求,又能维护DBS的安全和安稳。
(3)查询方法:
查询最大衔接数命令:show variables like’%max_connections%’;
查询当前数据库已树立衔接数:show status like ‘Threads_connected’;
(4)主张:
MYSQL官网给出了一个设置最大衔接数的主张比例:
Max_used_connections / max_connections * 100% ≈ 85%
即已运用的衔接数占总上限的85%左右。
2、超时时刻设置
(1)介绍
一次完整的恳求包括三个阶段:1、树立衔接 2、数据传输 3、断开衔接
connect timeout:假如与服务器(这里指数据库)恳求树立衔接的时刻超越ConnectionTimeOut,就会抛 ConnectionTimeOutException,即服务器衔接超时,没有在规则的时刻内树立衔接。 在数据库衔接设置中,connectTimeout表明等候和MySQL数据库树立socket链接的超时时刻,默许值0,表明不设置超时,单位毫秒。
socket timeout:假如与服务器衔接成功,就开端数据传输了。假如服务器处理数据用时过长,超越了SocketTimeOut,就会抛出SocketTimeOutExceptin,即服务器呼应超时,服务器没有在规则的时刻内回来给客户端数据。在数据库衔接设置中,socketTimeout表明客户端和MySQL数据库树立socket后,读写socket时的等候的超时时刻,linux体系默许的socketTimeout为30分钟。
(2)危险
拜访数据库超时刻太长,拜访数据量大或者扫描的数据量太大,导致数据库长时刻无呼应。链接被占用无法开释,会导致线程池被占满。因而,为了能够及时开释占用链接,其他事务对数据库拜访不受影响,所以要合理设置数据库拜访超时时刻。
JDBC的socket timeout在数据库被忽然停掉或是产生网络过错(因为设备故障等原因)时十分重要。因为TCP/IP的结构原因,socket没有办法探测到网络过错,因而运用也无法自动发现数据库衔接断开。假如没有设置socket timeout的话,运用在数据库回来结果前会无期限地等下去,这种衔接被称为dead connection。
为了防止dead connections,socket有必要要有超时装备。socket timeout可以通过JDBC设置,socket timeout能够防止运用在产生网络过错时产生无休止等候的状况,缩短服务失效的时刻。
(3)主张
一般状况,主张装备connectTimeout=60000,单位毫秒。主张装备socketTimeout=60000,单位毫秒。具体装备因体系而异。
总结
简单被忽视的数据库衔接运用健康度查看项,背面有着时区、超时时刻、衔接数设置不当或许带来的危险;依据运用实际状况并遵循设置原则进行合理设置,满意运用健康度查看项,才能防患于未然。