作者:京东零售董方酉

引言

运用健康度是反馈运用健康程度的目标,它将体系目标分类为根底资源、容器、运用、报警配置、链路这几项,收集了一系列体系运用的目标,并对目标进行打分。

运用健康度的每一项目标显现着体系在某一方面可能存在的危险和安全问题;因而进步运用健康度对于体系监控具有重要意义。知其然需知其所以然,了解运用健康度中的目标背后的危险,对于我们了解和提升体系安全性很有协助。

笔者作为后端研制工程师,一起在推动组内运用健康度进步的一起,依据遇到的问题现象,结合运用健康度进行分析,将逐一总结一系列运用健康度危险分析;

第一篇,我们来分析下简单被人忽视的数据库时区设置项可能导致的危险。

一、运用健康度查看项

数据库衔接池配置中,经过解析源代码获取,支撑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,单位毫秒。详细配置因体系而异。

总结

简单被忽视的数据库衔接运用健康度查看项,背后有着时区、超时时刻、衔接数设置不当可能带来的危险;依据运用实际状况并遵从设置原则进行合理设置,满足运用健康度查看项,才干防患于未然。