金融行业Elasticsearch API命令导致的生产故障

小夏 财经 更新 2024-03-04

关于作者:

李萌,他是数据领域的专家,是国内顶级的Elastic Stack实务专家,也是中国首批21位Elastic官方认证工程师之一。 他于 2012 年创立了 Elasticsearch,在 Elastic Stack 技术栈的开发、架构、运维、源代码和算法方面拥有丰富的实践经验。 他负责过多个 Elastic Stack 项目,包括大数据分析、机器学习、业务查询加速、日志分析和基本指标监控。 拥有超过10年的技术实践经验,擅长大数据、混合技术栈和系统架构。

序言

图:Elasticsearch目前在db-engine中排名第8位

Elasticsearch博大精深,提供了非常丰富的应用场景功能,以及丰富的API命令操作,有些API非常好用,有些API使用起来很难防范。

以下围绕某客户在客户端应用中误用集群状态命令展开,从问题定位到问题解决,记录自己的流程和方法,以及一些经验总结(注:具体客户信息不方便透露,以下部分**信息仅为示意图)。

一、案例介绍一、项目背景简介

客户使用ES解决日常数据查询和存储问题,并利用ES优异的水平扩展特性,满足多种场景应用。

ES 集群版本属于 56.已经超过Elastic官方支持的版本,集群中节点少于10个,节点硬件配置均衡一致,标准基于性能的硬件配置在合理范围内,应用于业务系统提供查询或更新等,并提供日常定期巡检, 基本正常稳定,但一直专注于集群运维本身,很少深入应用端程序进行检查分析,业务线太多,资金有限。

ES 集群配置不采用主节点与数据分离的设计,所有节点都具有相同的角色权限。 ES集群中的数据量也在正常支持容量范围内,集群索引中的分片数量在2W以上。

客户端应用基于 Spring Data Elasticsearch 开发框架,该框架引用了 trasnport-client 直连模式,不使用任何代理加载产品。

客户端应用部署多个实例,递增2倍,需要在ES集群中做一些“大”的数据写入和查询,以及瞬时并发操作,不管怎么操作,ES的并发性都不高,但是应用端程序就是运行速度不快,这是非常不合理和不合理的,常识告诉我这是不正常的。

图:客户公司应用项目架构示意图,客户端采用传输-客户端直连方式。

二、问题现象及事故原因

只要客户端应用开始运行,ES集群就会立刻变慢,但从ES集群的整体资源消耗来看,ES所在节点的CPU MEM硬盘IO并不高,其数据节点甚至很低,远远没有达到节点的瓶颈。

仔细观察发现,集群的主节点流量特别高,其他节点的数据流量传输到主节点,超出了主节点单节点网络IO的限制,明显异常。 但是,在生产环境中进行故障排除并不容易。 后来,在本地开发环境进行模拟压测后,最终确定问题是由客户端的集群管理操作API引起的。

最终找到了集群状态 api statistics 命令,客户端应用在做实际业务之前,每次都会调用这个 api 命令来获取集群的一些索引和映射信息,因为客户端是多线程的,部署了多个实例,只要并发数量高,所有流量都不可避免地会打到主节点, 导致整个集群的响应速度较慢。由于整个集群有近 2 个 W 分片,因此需要运行 state 命令收集集群中的所有索引分片,最后汇总到主节点,导致主节点的实际网络 I/O 超出限制。

图:集群状态 API 返回内容,索引越多,返回的内容越大。

二、调查过程与分析手段我们已经简要地谈到了问题现象和事故原因,现在我们将重点介绍问题排除过程以及所采用的工具和方法。

特别是由于远程协同分析排查和客户公司的行业特点,外部无法直接操作任何远程节点,必须由客户公司的运维人员间接指导操作和排查,过程略显曲折。

1. 检查服务器端集群

首先是ES集群问题的调查,这是一种非常正常和直接的思维,调查是在问题的爆发点进行(PS:类似于警察先赶到案发现场取证)。 由于集群版本为 56.X,由于一些原因没有开启官方的xpack功能,所以没有内置的Kibana监控可视化报表,国内早期用户大多都是在使用开源免费版搭建集群,客户公司基于Zabbix搭建了集群节点的基础指标监控,最后还有一个,非常罕见。

1) Zabbix监控与分析

很快,基于Zabbix,对每个ES机器节点的指标进行监控分析,按照常规例程,对CPU、内存、磁盘IO等进行分析,一切正常,但不高。 这是非常令人困惑的,显然集群响应速度很慢,客户端应用开发者也如实响应,而且部署的实例很少,所以经过初步分析,并没有明显的问题所在。

然后,对节点网络IO进行分析,发现问题点,其中主节点流量特别高,超出了网卡的限制。 按照这个套路,我继续查看其他数据节点的网络IO,也比较高,然后观察到数据节点的网络IO流量刚好等于Master节点的网络IO流量,终于找到了突破口。

需要注意的是,虽然Zabbix可以监控每个独立节点的网络流量,但它无法看到节点之间以及应用客户端和服务器之间的网络流量,这是非常不友好的。

图:Zabbix网络流量的图,提供单个节点的快速视图。

2) IFTOP监测与分析

在zabbix的帮助下,已经找到了突破口,下一步就是需要网络流量关联图。 这时,首先想到的就是对Elastic Stack Packetbeat网络IO流量报文的可视化监控和监控,客户公司当即讨论是否可以安装配置。 后来,客户公司的运维工程师临时安装了Linux网络命令iftop,终于能够分析出ES各节点网络中IO流量的流向,但观察分析比较辛苦,无法绘制网络图, 所以观察仍然不够全面。

iftop 只在单个节点上执行,所以你只能看到进出单个节点的网络流量,但这已经很好了,但需要更长的时间。

基于对网络IO流量进出的初步分析和观察,迅速做出决策,先重启已有的Master节点,让ES集群重新选择新的Master节点,但发现新选的Master节点的流量仍然很大。 然后,我也临时申请了新增 2 个 ES 节点,以为可以分散客户端访问的压力,但实际上并没有从根本上调研。 这时判断是,有些业务指标查询导致流量比较大,恰好在主节点中进行了转移和汇总,但是这里没有分析客户端的流量,所以做了一些无用的紧急服务器端调整,但也证明问题不在ES服务器上。

图:IFTOP网络流量示意图,可以分析单个节点的流量进出,也不错。

3) Packetbeat 监控分析

由于某些原因,Elastic Stack 监控分析产品没有部署,尤其是 packetbeat 网络流量监控分析产品,官方默认提供的网络流量图非常有用,可以更快速地定位流量方向,相比 ITTOP,更全面,可以概括为网络版的 IFTOP。 PacketBeat 内置了一些官方可视化报表,如果觉得还不够,可以根据 ES 提供的分析能力自行设计。

图:PacketBeta网络IO流量监控分析图表、输入和输出。

2. 客户端故障排除

第二种是从客户端应用进行检查。 但事实上,当客户公司的运维人员发现问题并第一时间联系我时,我的第一个问题是客户端应用在做什么业务,业务类型是什么。 运维人员也如实告知了正在做的业务类型和应用,其实我只能总结一下,并不知道详细的业务运营流程和影响,对我来说,反正我知道有业务运营影响集群,还要继续调查到底是怎么影响的。 必须说明的是,这可能是国内IT运维行业的一个通病,似乎运维属于端支撑,本质应该更多地参与到业务系统的前沿,而其背后的运维问题应该从业务中去理解。

然后,通过ES服务器端的排查,已经掌握了一些信息,但是远远不够定位问题,客户端排查还有很长的路要走,必须找到问题。 ES集群中有很多慢响应,但是服务端只能发现问题,却无法从根本上解决,所以通过在服务器上运行线程池和任务命令,发现集群的管理线程池非常大,任务一直都满载着, 这是不正常的,这更能确定客户端的某些应用程序一定是恶意操作这些命令。

1) 线程池监控与分析

集群响应慢,集群线程池是必须考虑的一个点,会看到累计任务量,打开指令观察后,管理线程池特别高,所以判断客户端正在做一些任务,并且属于管理线程池,具体还不确定, 因为客户端应用程序没有看到特定的**调用模式。

图:线程池示意图,用于监控 ES 节点上的任务数。

2) 任务监控和分析

借助线程池分析,您可以定位管理线程池来大规模执行任务,并使用该任务查看正在分析的具体任务。 (ps:在实际客户环境中,发现有大量的状态和统计任务,其中状态任务数量明显高,非常异常,这里不方便透露,这个结果如何压测,后面会详细列出)。

图:任务的示意图,可用于查看特定任务类型。

3)统计监控分析

借助任务监控分析,发现有大量的统计指令,然后在服务端执行一次,看看情况如何,实际响应速度比较慢,但逻辑上正常,生成的队列数量不高, 但是执行速度较慢,根据上面的判断,应该是其他任务阻塞造成的。

stats 负责集群监控和检查响应,常规集群黄、红、绿三色由此而来; 另外,它还收集索引和节点的统计信息,返回的数据量不多,所以一般可以忽略,但要注意后期需要传输客户端访问。

图:stats 命令执行示意图。

4) 状态监测和分析

借助任务监控分析,发现有大量的状态指令,然后在服务器上执行一次,找到了问题点,执行时间很长,响应返回的内容超过70MB,这就是问题所在,可以回答为什么之前的主节点流量这么高。 最后,问题变得越来越清晰和确定。

图:状态命令执行示意图。

5) 传输客户端应用程序访问

借助前面的服务器端现象分析,越来越确定问题出在客户端应用**上,最有可能的是操作错误。

首先,与客户沟通,让客户端应用**访问ES和程序版本,客户端开发团队配合很好的,很快就得知应用客户端是基于Spring Data Elasticsearch框架的,使用transport-client机制来访问操作ES,但是这时候无法定位为客户端导致的, 也不能要求客户匆忙提供源代码。不久之后,相应的测试程序源代码在本地编写。

传输客户端绑定。

模拟 Spring Data Elasticsearch 配置 transport-client,示例来自官方文档*

configuration

public class transportclientconfig extends elasticsearchconfigurationsupport

bean(name = )

public elasticsearchtemplate elasticsearchtemplate() throws unknownhostexception

6)JMe压力测试模拟

由于某种原因,我们只能提供间接服务,所以为了彻底解决上述问题,我们需要在本地模拟测试,并且必须先模拟生产问题,然后才能要求客户端提供源代码。 根据之前从服务器和客户端应用中学到的信息,下一步是做一个压力测试,特别是选择jmeter工具,快速配置本地集群,并附加客户端应用访问**。 在压力测试过程中,可以同步观察ES服务器的ThreadPool和Task,并可以重现生产问题,并快速获得所需的结果。

图:JMe压测示例,开启线程数,线程数超过ES测试服务器上的线程数。

图:JMe压力测试示例,一个状态命令的执行会消耗大量资源。

由于在生产中也发现了同样的问题,借助 jmeter 压力测试在本地环境中,最后一步是审核客户应用开发团队,速度非常快,很快就能找到客户应用端,然后再进行具体的业务操作,就会调用集群状态 api 来判断业务逻辑, 确定索引是否存在,确定索引字段是否存在等。

最终,问题找到了,原因知道了,事情也就结束了。

对客户申请的访问。

使用状态确定索引的映射信息

public map getmappingbyfield(string indexname, string type) throws ioexception

map mapping = mappings.get(type).getsourceasmap();

map properties = (map) mapping.get(es_properties);

return properties;

3. 回顾问题分析过程

服务器端分析,寻找突破口。

客户端分析,以缩小故障排除范围。

模拟测试以复制生产问题并确定问题的原因。

分析应用端,找出问题所在。

修改观察结果以确认问题已解决。

吸取的经验教训,审查所有其他相关**。

图:故障排除过程和过程。

3. ES技术架构原理

本次 ES 故障排除涉及到很多知识点和技术原理,这里专门讲解与此相关的架构原理,供大家日后参考和分析。

1. ES架构原理

虽然 ES 声称是可以水平扩展的分布式架构,但它指的是数据节点或其他非管理节点。 实际上,ES 是一种典型的主从架构模式,一个集群只有一个活跃的主节点,主节点负责管理集群的所有元数据信息,包括节点信息、索引信息、分片信息、节点和索引路由信息、节点和分片路由信息等,集群需要先在主节点中执行一个管理命令, 然后将其分发到其他节点。

这对于理解和解释为什么主节点的网络流量正好等于此 ES 故障中其余节点的网络流量之和非常重要。 当客户端应用发起状态计数时,主节点先接受指令,然后分发给其他节点进行状态统计,最后汇总到主节点,导致主节点网络流量极高,超出网卡限制,ES集群响应缓慢, 但实际CPU和内存消耗并不高。

随着集群规模越来越大,大老板的压力越来越大,如果大老板失败了,大老板就会连任,这听起来好像不符合社会组织。 下次能不能修改一下,设计一个大老板和第二个主人的模型,然后把大老板和两个主人的职责分开,大老板太忙了,两个主人分担一些。

图:ES主从架构的分布式示意图,集群只有一个活动主节点。

2. ES线程池

ES是内部设计了多个任务线程池的数据库产品,不同的线程池有不同的任务和职责; 线程池也分为各种类型,不同的线程池类型响应不同的任务场景。 线程池的数量和类型因 ES 版本而异,尤其是在 5 中x 与 7X版,这种跨专业版,差别挺大的。

作为机构的ES老师,我经常与J**A学生交流,发现了一些严重的认知误区: 1很多同学认为,由于GC机制的原因,J**A无法开发数据库产品; 2.大部分人学习掌握 J**线程池只用于简单的多线程业务场景,从未想过 ES 集成了几十个线程池。 因此,必须承认,ES对于J**A开发大师来说是一个非常好的产品,特别是对于做后端开发,想要更深入、更高级的同学来说。

了解 ES 线程池的内部设计非常重要,这可以解释为什么在这次 ES 故障中,只有 Active Master 节点的管理线程池特别忙,其余的线程池一般都非常空闲,其余节点的线程池也非常繁忙。 客户端应用发起状态计数,第一个接收任务的任务是主节点的管理线程池,线程池类型为伸缩,最大线程数为固定值,不超过实际CPU复合数,也不能超过固定值5, 而不是根据节点的CPU核心数自动弹性设计。

当客户端应用采用多线程执行模式时,每次在执行业务操作之前,都会执行一次状态统计,做出业务逻辑判断,无形中增加了集群的负载和主节点的任务数量。 正是因为负责执行状态任务的线程池是固定值,主节点的CPU不会满,导致所有业务操作受阻。

有时候官方文档没有列出,需要通过ES源码来检查,我还是没弄清楚,不仅在以前的历史版本中,而且在现在的最新版本中,比如现在的715.x,有些线程池在官方文档中没有列出,但可以在集群监控中查看。

图示:ES 内部线程池划分(版本 7。13.x,来自机构的 ESVIP 课程)。

ES 线程池初始化源码:orgelasticsearch.threadpool.threadpool */

public class threadpool implements reportingservice, scheduler

3. ES集群统计的执行过程

集群状态 API 执行一条指令一次,指令传输到主动主节点,主动主节点将指令分发给每个节点,每个节点收集信息并发送回主节点,然后主节点响应客户端。

在故障排除之初,最初的判断是错误的,认为客户端在做大量的业务数据查询任务,并且所有节点的数据量都很高,其中很多都依赖于主节点的外部输出,但事实并非如此。

图:集群状态API执行过程示意图。

4. ES动态创建索引

ES是典型的免费schema数据产品,可以动态创建索引,也可以动态创建索引字段,无需优先级声明,也无需逻辑判断应用中是否存在**,是否需要创建,这是ES非常优秀的动态扩展能力之一, 基于此为应用开发带来了很多便利,比如著名的“大宽表模式”查询场景,解决了海量数据关联的实时查询问题。

ES可以提前创建索引,也可以不创建索引,可以通过写入第一条数据来动态创建索引,同时可以自动映射索引的内部结构。 如果在第二次数据写入中添加了大量新的数据内容结构,则当前索引的映射将自动更新,并且映射将自动刷新。 如果缺少新添加的数据字段,则不会出现错误。 默认情况下,ES 内部会根据字段计算字段的类型。

动态创建空索引。

put my-index-000001

添加数据,动态创建索引,并自动估计字段类型。

put my-index-000001/_doc/1

create_date": "2015/09/02"

更新数据并动态添加新的字段类型。

put my-index-000001/_doc/1

my_float": "1.0",

my_integer": "1" ,"create_date": "2015/09/02"

5、transport-client

Transport Client 是早期正式推出的应用访问机制,自 REST API 上线以来,官方一直试图要求切换,原因没有具体说明。 transport 是一种直接连接方式,直接连接到 ES 集群,连接后保持持久连接,需要定期执行一些内部 stats 命令来检查集群监控状态,这实际上是非常冗余的,极端情况下会消耗集群资源。

ES 集群中其他指令的内部通信或执行是通过 Transport 机制进行的,即使由 REST API 执行,也会在内部转换为 Transport 机制进行执行。

REST访问比传输更解耦,也可以尽量避免恶意干扰传输通信。

图:transport-client 和 REST API 之间的连接示意图。

四、专家建议

这一次,花了几天时间才找到问题,定位问题,解决问题,还有一些经验建议需要解释。

1.全面的监控系统

监控系统是运维之眼,集群的各类运行信息需要借助强大的监控系统来提供实时分析。 在这种情况下,客户公司的监控系统比较传统和落后,虽然有Zabbix,但在一些新的问题分析方式上并不好,而且非常缺乏,比如分析集群每个节点的流量,包括服务器和客户端之间的关系。

选择一款全面且具有非常独立视角的监控产品非常重要,而 Elastic Stack 是新时代的产品,可以帮助我们改进优化故障排除思维。

2. 权限安全隔离

大多数数据库产品都提供了一些基本的安全策略和保护,可以通过设置一些安全用户组和角色权限来限制这些策略和保护。

例如,传统的关系数据库 MySQL 可以通过为客户端应用程序分配较少的权限来限制。 在早期的 ES 版本中,由于 ES 没有提供安全保护机制,很多应用团队直接使用它,并没有实现基于用户组的权限隔离。 最新版本的 ES 提供了开源且免费的基础安全策略,可以避免客户端应用程序通过用户组权限进行无意操作。

3. 全面的知识体系

在这种情况下,从集群的后端运营分析,到应用端的源码分析,再到本地环境的仿真测试,涉及的技术点非常广泛,无法从单一维度发现和解决,也不能仅从ES知识层面解决。 没有人可以只从ES集群中跑出表面定位问题,很多问题都在尽头,但原因其实在另一端,这需要跨界能力和思维,当然最重要的是建立自己的知识体系,有自己独立的解决问题的想法,也要掌握必要的工具和软件, 不仅限于 ES 的范围。

为了用好 ES,我们需要掌握开发技能,熟练使用 ES 提供的开发特性,了解 ES 各种特性的边界,防止滥用。 我们需要掌握ES集群架构的基本原理和基本操作机制,避免认知误区,比如ES是典型的主从架构分布,而不是无中心分布。 我们需要掌握一般的运维技能,从操作系统的基础环境到ES运行的各种指标信息。

4. 全栈工程师理念

随着业务需求和社会的发展,我们需要更多的全栈工程师,当然也要说明,不需要一个工程师同时承担多个工作,也不是按照国内一些企业的“挤全栈”的说法。 相反,强调工程师的专业水平,工程师可以根据自己的工作岗位轻松转换角色,而不仅仅是固定的岗位。 很多优秀的IT产品,不是由在自己工作岗位上工作的人制作的,而是由一些跨界人士制作的。

在这种情况下,看似集群的问题是服务器,其实是开发知识的局限性造成的,最终的解决方案也是修改应用端来解决,这是一个典型的跨界问题,逐渐被服务器发现是应用端的问题。 为了模拟生产环境的问题,需要使用压力测试工具,这似乎是测试的责任,但为了解决问题,有必要从后向前工作。 为了确定线程池设置问题,对应的版本源码,去检查并阅读相应的线程池设置,因为官方文档没有。 若要识别客户端应用问题,请根据客户端开发人员提供的信息编写模拟的客户端应用行为。

目前,公司在中国的工程师大多是单一职责的岗位和技能,尤其是专注于前后端分离后,前端和后端的技能比较认真,前端很多工资都很高,上升速度快,看不起后端, 后端逐渐远离前端应用,更关注前端操作模式;后端应用和大数据开发也分离,将大数据开发与应用开发分开,导致工程师的专业素质迅速下降,很多大数据工程师没有良好的编程技能,这是一个值得思考的问题。

引用

状态参考文档。

ThreadPool 参考文档。

Elasticsearch 传输客户端参考文档。

Spring Data Elasticsearch 参考文档。

JMemeter HTTP 请求参考文档。

DBAPLUS 社区欢迎 editor@dbaplus 技术人员的贡献cn

相似文章

    国际广场欢迎

    上海优友国际广场由上海友友集团斥巨资打造,位于上海繁华的浦东新区浦建路,犹如一颗璀璨的明珠,熠熠生辉。这个广场既是商业中心,又是集休闲 娱乐 商务于一体的综合性建筑。广场的N地块是一幅气势磅礴的层喜来登五星级酒店和优雅的层公寓酒店的生动画面。他们并肩而立,仿佛是两个优雅的舞者,在繁华的都市中翩翩起舞...

    相对于心灵,疾病源于内心,幸福生活的根源来源于心态很重要

    病源于心 是一句中国谚语,意思是一个人的容貌和健康往往反映出他的内心状态和情绪。发自内心 是指一个人的外表和举止往往能反映出他的内心世界和性格特征。例如,一个善良 开朗的人往往会表现出和蔼可亲和友好的举止,而一个焦虑 紧张的人可能会表现出皱眉和苍白的肤色等特征。发自内心的疾病 是指情绪和心理状态对身...

    祝福由心生,心由仁滋养

    人生的道路充满了曲折。每个人都在寻找自己的幸福,而幸福,到底是 吗?事实上,幸福不在别处,而是在我们的心中,由我们的善良和爱滋养。在这个复杂的世界里,我们常常被金钱 名利 地位等物质欲望所困扰,以至于忽略了内心的善良和爱。然而,真正的幸福并不来自这些物质欲望的满足。相反,只有当我们用心关心他人,善待...

    祝福由心生,心由仁滋养

    无比的喜悦。心胸宽广,不仅是人生的修行,更是人生的智慧,能为我们创造一个平安的环境,一个幸福的当下。安心和幸福。一个安静的人是一个拥有平和 平和 清晰头脑的人。他们不为外界的干扰而动摇,不为内心的欲望所困扰,不为过去的遗憾而难过,不惧怕未来的未知。他们能够珍惜当下,接受不可控的,不抱怨,不抱怨,不执...

    是什么导致了地震

    是一种自然灾害,通常由地球内部的构造活动引发。的成因复杂多样,涉及地球物理 地质学 科学等多个学科。下面将从地球内部构造 板块构造理论 火山活动 人为因素等方面解释 的成因。.地球的内部结构。地球内部由三层组成 地核 地幔和地壳。它主要发生在地壳中,地壳是地球最外层的地壳,分为几块,称为板块。地壳下...