苏宁易购发展到今天的规模和体量,对苏宁IT提出了更高的要求,特别是在运维方面,提出了更高的响应和保障要求,整个运维体系也是在不断提升自动化处理能力和水平,为苏宁易购的快速成长做好后端保障。
在中间件运维方面,我们开发了相应的中间件运维工具支撑大规模的中间件配置及巡检,提升配置标准化的能力和系统稳定性。在工具的建设过程中,我们不断探索新技术,提升对大规模运维的并发处理能力。在WildFly的配置巡检上,我们取得了较大突破,实现了效率和性能的双重提升。
从系统上线到运维,从手工配置到自动化配置,多部门协同工作,导致出现各种配置不一致、不标准、甚至缺失的情况,这些运维中的痛大家都遇到过,配置巡检是运维必不可少的一项工作,对于我们来说,检查点在以下几方面:
1、应用中的数据源连接池最大连接数是否超出数据库配置的最大连接数;
2、应用中数据源是否配置了数据库的高可用方式;
3、数据库主备配置的最大连接数是否一致;
4、废弃的数据源配置是否从环境中删除;
5、JMS是否配置了主备信息。
这些检查是要保证我们的配置无误,对应的主备、高可用配置检查,都是为了确保后端数据库发生宕机做主从切换后,前端应用可用自动恢复,无需人工干预,尽快恢复系统的可用性。对应的数据源连接池的大小配置,也是为了保证数据库的安全,避免应用与数据库的连接过多引起数据库的故障造成较大的影响。
我们现在应用服务器数量比较多,架构也存在多种,人工巡检已经不现实,工作量太大,效率、准确性都无法保证,我们只能往自动化巡检方面发展。
在我们目前使用规模最大的WildFly方面,我们经过一段时间的发展,在自动化巡检方面探索出了更为高效的方法,提升了我们整个中间件配置巡检的效率。
由于WildFly官方文档比较少,能参考的不多,我们在负责中间件运维的同时去开发运维工具,时间太碎片化,进度方面难以保证,经过三个阶段的发展,终于找到了高效的方法,实现了我们一个小目标,我们一直痛并快乐着。
现在生产环境规模比较大,仅WildFly虚机已近30000台,我们使用python开发了批量巡检的脚本,并实现web化管理,方法如下:
1、将通用的python配置巡检脚本传输到每台服务器上;
2、脚本中调用本地jboss-cli.sh命令去获取jboss的相关配置信息,包括jdbc、jms等配置,因涉及多项配置信息,循环获取详细配置属性,需要调用本地jboss-cli.sh命令次数不定;
3、Python脚本将获取的原始配置数据整理成json数据,然后将json数据返回到本地脚本,入库保存;
4、再跑不同的脚本去解析详细的配置数据以及核查配置,最终导出到Excel文件供运维人员逐一核查处理。
Jboss-cli方式可以很方便的获取到格式化的配置信息,也可以在线进行jdbc、jms等配置,可以实时动态的修改日志级别,用起来可谓是优势显著,既提升效率又不虞有修改配置文件出错的顾虑,是自动化、标准化实施配置的极佳选择,而且在文档极度缺失的情况下,这个命令在写的时候可以自动补全和提示,极大的方便了我们去获取我们需要的信息。
这个方法可以核查出大部分的异常配置数据,是自动化的第一步,降低了运维人员手工核查的工作量,将工作精力放在存在问题的配置核对和修正上,收效明显。
1、由于jboss-cli本身执行的问题,容易出现配置获取缺失的情况;
2、数据源连接数计算不是非常精准,容易出现偏差;
3、这种方式获取一次,并完成解析和校验,在不限制线程数量的情况下仍然需要5个小时以上,效率比较低;
……
之前的方法存在各种使用上的不足,自动化程度、效率有待提升,导致我们只能在每次大促之前的一段时间批量处理一次,这就导致每次大促前会检查出很多配置需要修正的情况,要么修改数据源配置,要么修改数据库连接,这样非常不利于系统的稳定,而且这种集中式的处理也增加了项目组和运维人员的工作压力。
我们调整了整个配置获取、解析、核查的方式,在配置获取完成后直接在线程中解析详细配置以及计算连接数,解析和计算完成后直接将结果入库,将存在问题的配置数据展示在前端页面,便于运维人员随时查看和处理。
这种方式极大的提高了单次配置获取、解析、核查的效率,并将核查频率由之前的每次大促前一次提高到每周一次,便于运维人员在平时就可以修正配置,将大促前的一次性工作改变为日常的运维工作,在日常工作中解决风险,是运维模式上的一次较大的改变。
1、这种方式仍然没有解决数据计算不精确的问题;
2、jboss-cli.sh命令会在本地启动一个将近80MB的独立进程,脚本中循环调用该命令,会在短时间内频繁的新建这样的进程,会造成机器大量的性能损耗,我们只能放在夜里跑任务,也经常有项目组找到我们询问服务器CPU在夜间告警的问题;
3、单次全量获取和解析速度依然无法满足我们的需要。
就是WildFly这么一种自带光环的配置方法和工具,在实际使用过程中却出现了瓶颈,在执行的时候会启动独立的进程,而且对CPU资源消耗较高,在后面的测试对比中有数据说明,这样的结果让我们的应用场景也受到了限制,不能影响业务系统本身的资源使用,将数据抽取的任务放在凌晨业务低峰期的时候进行,频率只能一天一次,遇到大促这种场景,还得暂停任务,将资源全部让给业务系统。
我们总结了之前的问题,集中在服务器性能的消耗和效率上,我们开始研究新的配置获取方式:
1、不再使用jboss-cli的方式去获取配置信息,而是采用http的方式,以降低服务器性能损耗;
2、由于使用了http方式,连接数的计算也不再依赖本地数据,全部基于jboss获取的数据信息,以提升数据的计算精度。
但是官方网站的doc文档对HTTP+management+API的描述极为简单,仅有为数不多的文字描述和和寥寥无几的样例,查遍第三方技术论坛几乎没有任何相关资料,因此每一个http的接口都需要我们慢慢尝试和探索。
根据官方的doc文档我们知道:
1、HTTP+management+API包括GET方式和POST方式2种;
2、HTTP+management+API符合REST风格;
3、接口需要用户名和密码;
4、接口需要设置头信息。
根据这些信息,我们一开始只推测出一些post方式的配置查看的API,但是我们业务需求只需要获取配置信息,无需传递数据去新增、删除和修改配置,所以不太适用于我们的业务场景,而且使用这种方式有明显的缺陷:每个配置项都要单独调用一次http请求,对于jdbc和jms的每个自定义属性也都要单独调用http请求去获取。这种方式仍然需要N次调用接口,依然需要消耗服务器的性能,所以转而去探索GET方式获取配置信息的方式。
终于在不懈的探索和尝试之后,我们把获取standalone模式的单个节点全部jdbc、jms配置的所有信息的HTTP+management+API的调用次数压缩到了3次,domain模式的压缩到了不超过5次。而且接口调用返回数据几乎是秒回,效率提升非常显著。
获取概要信息:此接口可以获取部署的应用包、节点信息和组信息等
curl --digest 'http://username:password@ip:9990/management'
获取所有数据源详情:此接口可以获取该WildFly上配置的所有数据源的所有信息,包含自定义属性和值,如果不需要详细信息可以去掉recursive这个参数。
curl --digest 'http://username:password@ip:9990/management/subsystem/datasources/data-source?recursive'
获取所有MQ队列和MQ队列工厂数据:(wmq.jmsra.rar是IBM MQ驱动包文件),这个参数可以获取该WildFly上的所有MQ队列和队列工厂的数据,如果不需要详细信息可以去掉recursive这个参数。
curl --digest 'http://username:password@ip:9990/management/subsystem/resource-adapters/wmq.jmsra.rar?recursive'
对于domain模式的集群只要在management/subsystem之间添加一个profile的信息(profile/$profile),如此即可:
curl --digest 'http://username:password@ip:9990/management'curl --digest 'http://username:password@ip:9990/management/profile/$profile/subsystem/datasources/data-source?recursive'curl --digest 'http://username:password@ip:9990/management/profile/$profile/subsystem/resource-adapters/wmq.jmsra.rar?recursive'
目前实验出来的并且知道作用的参数:
在经历了一段时间的盲目并且不懈的探索后,发现这种接口探索效率低下,收效甚微。而且在技术论坛也查找无果的情况下,我们想到cli方式和http接口方式的底层处理方式应该是一致的,所以接口的层级关系应该也是相似相通的。所以希望借助cli自动提示和补足的功能,探索每个数据项的层级关系,这样可以逐步知晓HTTP接口的层级关系。实际情况是这种方式确实有一定用处,但是随着摸索工作进一步深入才发现:两种接口方式还是有较大区别。
在这个时候,探索工作一度陷入停滞不前的状态。“山重水复疑无路,柳暗花明又一村”,在一次摸索的过程中无意中发现了recursive这个参数,这个参数可以获取当前层级及以下层级的所有数据。于是果断借助recursive参数调用 curl --digest 'http://username:password@ip:9990/management?recursive'
这个接口一次性获取全量数据,然后根据这个接口返回数据的层级关系,再逐步探索HTTP management API接口便轻松自如多了。但是这个接口有个明显的缺陷,就是:获取数据量太大、太全,导致接口返回数据比较慢,当然在这过程中,对服务器的性能损耗也是更高的。所以在获取配置的时候我们没有选择使用这个接口。
这里只介绍这3个我们目前用到的接口,我们也摸索出来了一些获取各种运行时数据的接口,有机会可以与大家详细交流,这里不再赘述。
切换了获取配置信息的方式后,对服务器的性能损耗已降到很低,获取配置的持续时间降到很短,为了对比两种方式的性能提升,我们采用1台2C4G的standalone的机器做了测试对比。
测试环境:
虚机配置:2C4G
整体CPU消耗:\u0026lt;1%
WildFly实例:1
war:1
jdbc:10
jms:26
场景一:
Jboss-cli方式连续(串行)10次获取全量jdbc、jms配置
执行时间:10:43:08 ~ 10:50:43
耗时:2分44秒
CPU使用:\u0026gt;60%
Http方式连续(串行)10次获取全量jdbc、jms配置
执行时间:10:57:37 ~ 11:00:21
耗时:7分35秒
CPU使用:\u0026lt;3%
场景二:
Jboss-cli方式并发10次获取所有jdbc、jms配置
执行时间:14:38:31 ~ 14:44:43(最迟)
耗时:6分12秒
CPU使用:\u0026gt;85%
Http方式并发10次获取所有jdbc、jms配置
执行时间:14:55:06 ~ 14:55:25
耗时:19秒
CPU使用:\u0026lt;7%
通过以上对比数据可以看出,在串行模式下http方式比jboss-cli方式获取配置信息的效率提高了1.77倍,CPU资源使用降低了19倍;在并发模式下http方式比jboss-cli方式获取配置信息的效率提高了18倍,CPU资源使用降低了11倍。可见,http方式比起jboss-cli方式具有资源消耗低、效率高的特点,在jboss配置巡检上极具优势。
以上并发场景应用在我们实际环境中暂时体现不出来,我们目前是单实例的部署架构,每个实例只需要执行一次。
在实际应用中效果会更为显著,以现网5万个wildfly实例为例,粗略估算一下,按1000并发执行,需50次,使用jboss-cli方式,按平均每次耗时45s算,大概需要37分钟;使用http方式,按平均每次耗时16s算,大概只需要13分钟。
以上对于单个实例的配置获取方法采用的是串行模式,先获取到应用包的信息,再获取jdbc和jms的列表,之后再从列表中循环读取每个jdbc和jms的属性。鉴于http的高并发特点,可以对获取方法进行优化,获取到jdbc和jms列表后,采用并发模式获取每个jdbc和jms的属性,在时间上将会有更大的缩减,而对服务器资源的使用不会有明显的升高。
采用这种方式的收益,不仅仅是节省时间,之前由于jboss-cli的方式占用CPU资源较高,配置抽取的任务只能放在夜里业务低峰期的时候进行,每天只能抽取一次,配置的更新频率很低,而采用http方式以后,它占用CPU资源极低的特点,再加上执行时间短,可以大大提高抽取配置的频率,一小时一次,甚至于半个小时一次,配置库做到准实时更新!
配置巡检的效率提升、对业务服务器资源占用的降低,是我们保障大促能力的又一大提升。
以前我们会在大促前对中间件配置进行一次全面巡检,对不合理的配置进行集中调整,时间仓促,变更密集,存在较大的风险。这次在双十一大促前夕,我们对配置巡检方法的根本优化,将原来在大促前的巡检工作放在日常进行,将集中的配置调整放在日常完成,对配置问题做到及时发现,及时处理,消除了大促前的集中变更风险。
今年的双十一大促,中间件配置巡检之路已平,运维保障,我们整装待发!
单隆声:苏宁易购中间件运维团队负责人,负责中间件运维团队建设及运维工具建设工作,在中间件运维工作上有丰富的经验,在中间件运维工具建设上,坚持逻辑严谨、操作简洁的设计标准,以提升运维效率、标准化能力为目标,持续推进运维自动化及标准化落地。
李照刚:苏宁易购中间件运维团队技术经理、运维开发工程师,负责中间件运维工具的设计开发工作。在python脚本开发上有丰富的经验,勇于钻研新技术,加入苏宁运维团队后,对中间件运维平台进行了较大的优化,不断完善平台功能,提升执行效率。