一次奇怪的事故:机器网络连接打满,导致服务不可用

news2024/11/24 14:24:49

业务背景

发生事故的业务系统是一个toB业务,业务是服务很多中小企业进行某项公共信息指标查询。系统特点:业务处理相对简单,但是流量大,且对请求响应要求较高:

业务请求峰值qps达50w,平时流量达20w左右。
请求响应时间需控制在50ms内。

系统整体架构如下:
在这里插入图片描述

为了方便下文描述,我简化一下业务处理逻辑:根据请求的内容,从数据库中查询对应的结果,然后返回,为了支撑大并发,把数据库中的数据全部缓存到了redis中,简单来说就是查询redis,返回结果。

业务系统的实现技术也比较常规,采用springboot+redis来完成。为了保证系统的高可用性,我们在系统的入口处添加了限流处理,正常单机可以处理1w并发,为了防止系统过载,限流阈值设置8000qps,超过8000的流量会进行降级处理:返回一个默认值。

在这里插入图片描述

整个业务服务集群70台机器,可以轻松抗住50w并发

系统自上线后的半年多的时间内,都比较稳定。不过就在前几天出了一个奇怪的问题。

事故描述

业务系统的前端的slb告警:新建网络连接过多

但是同一时刻后端服务的负载却是正常的,过了几秒后,
slb告警:与某几个后端服务实例健康检查失败

随后该后端服务实例,从slb上被摘除,实例上流量跌零

看到这一连串的告警,瞬间觉得很懵逼:发生什么事了?这个时候,查看监控,业务请求的qps并没有出现异常流量,请求的qps在45w左右,远没有超过系统容量。

查看日志发现:后端服务和redis之间的网络在刚刚出现了一点抖动,但是很快就恢复了正常了。

为什么后端服务与redis之间瞬间的网络抖动,会触发这么一连串的问题呢?更何况现在后端服务已经恢复了正常?

既然现在后端服务是正常的,那么就对这几个实例进行重启,实例重启后,实例重新注册到了slb上,流量正常进入,一切又恢复了正常。

事故起因

虽然线上问题解决了,但是我们心中的疑问并没有解决。

冷静过后,开发同学对刚刚的问题进行了复盘:为什么后端服务与redis之间短时间的网络抖动,会导致slb上连接被占满呢?看着两者好像没有什么关系

通过观察事故发生事件段内的监控和日志:
网络抖动期间,服务器实例创建了大量的网络连接,新建网络连接超过10000多个,平常只有几百个。

结合日志和监控,系统出现问题的大致流程如下:

后端服务与redis之间网络抖动,使服务实例与redis进行了连接重试,导致在那段时间内,该服务实例对请求的处理变慢

但slb到该实例的请求转发还是正常,因为后端服务请求处理的比较慢,所以slb需要和后端服务建立新的网络连接来进行新的请求的发送,新建连接发送的请求,被处理的速度依旧很慢,所以需要不断的建立新的连接,很快导致该实例所在的机器的网络连接被占满。

机器网络连接被占满后,slb再将请求转发到该机器上时,网络连接的建立就会被阻塞,直至超时,而超时后,slb又会进行重试,导致出现的大量链接建立行为,也就出现了slb连接创建过多的告警,这个时候slb与该实例的健康检查请求也会出现问题,导致该实例从slb上被摘除。

问题分析

问题的原因虽然找到了,但是这里还有几个问题需要继续讨论一下:

后端服务的限流配置是:该服务实例1s最大可以处理8000个请求,而网络连接被打满时,最多可以建立8000个链接,难道限流没有生效吗?

通过查看日志发现,事故时间段内,并没有达到限流的条件,也没有进行限流相关的处理。

看到这里就有点想不明白了,为什么创建了8000个链接,却没有触发限流呢?

其实这里要了解一个springboot中tomcat中关于网络连接相关的配置了,下面是本项目中关于tomcat的配置:

server:
  tomcat:
 	accept-count: 1000
    max-connections: 8000

tomcat网络连接管理模型如下:

在这里插入图片描述

maxConnections:

服务程序可以在一定时间内接收并处理的连接数目如图1中queue-2,超过这个数,会根据acceptCount 这个值继续建立连接存放在queue-1中,但是该连接不会被处理,只有当queue-2中的连接数小于maxConnections值,queue-1中的连接才会进入queue-2中,该连接才有可能被执行。queue-2中的连接状态如图2标注所示。当同时请求数大于maxConnections+acceptCount 时,新的请求将会被拒绝连接。

acceptCount

超过maxConnections这个值的连接数将根据acceptCount这个值继续建立连接,如图1 queue-1,当queue-2的连接数小于maxConnections, queue-1的连接进入queue-2.

maxThreads:

服务程序可以同时处理的线程数如图1 ThreadPool,可以理解为通过设定 maxConnections=10 ,同时可以建立10个连接,maxThreads=3,则这10个连接中同时只有3个连接被处理,其余7个连接都在queue-2中等待被处理,等这3个连接处理完之后,其余的7个连接中的3个才可以被处理。如果处理完的3个连接关闭后,queue-1中就可以有3个连接进入queue-2。

总结来说:当客户端发送请求时,完成三次握手建立连接后,先进入queue1中,然后在转移到queue2中,然后在被ThreaPool中的线程处理。

我们系统中 maxConnections参数值 是8000,也就是进入系统的最大并发也就是8000,当系统请求处理比较慢时,系统中进行8000qps的限流,其实是不起作用的。

当服务业务处理变慢时,也就是ThreadPool从queue2中取出请求速度变慢了,那么queue2就会变满,进而queue1也会变满,此时,当再有请求过来时,就会等待,直到queue1空出一个位置,或者请求连接建立超时。

解决方案

到这里,我们明白了为什么机器实例的链接会被打满,以及系统服务的限流降级策无法生效了。

解决方案就比较简单了:
首先出现上述一连串问题的根本原因是:实例机器网络连接被占满。
所以解决方案的出发点就是:避免实例机器网络连接被占满,因此需要把maxConnections 和
我们将 acceptCount设置大一些

同时给业务系统添加请求处理响应时间的限流和降级策略。

这样可以保证流量都能进到系统中,而不至于连接建立失败,只是超过系统可承载的部分被限流出去了。

调整后的系统架构图如下:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1472843.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

18 SpringMVC实战

18 SpringMVC实战 1. 课程介绍2. Spring与Spring MVC环境配置 1. 课程介绍 2. Spring与Spring MVC环境配置

Nginx之rewrite重写功能

一、rewrite概述 1、rewrite功能 访问重写 rewrite 是 Nginx HTTP 请求处理过程中的一个重要功能,它是以模块的形式存在于代码中的,其功能是对用户请求的 URI 进行 PCRE 正则重写,然后返回 30 重定向跳转或按条件执行相关配置。 Nginx服务…

JSON简介以及如何在Python中使用JSON

什么是JSON? JSON是"JavaScript Object Notation"的简称,是一种数据交换格式 JSON格式 假设我们有一个对象,这个对象有两个属性:“name”跟“age”。 在JSON中是这样表达的: { "name":"男孩…

51.仿简道云公式函数实战-文本函数-JOIN

1. JOIN函数 JOIN 函数可通过连接符将数组的值连成文本。 2. 函数用法 JOIN(数组,"连接符") 3. 函数示例 如需将复选框中勾选的选项通过”-“组合在一起,则可设置公式为JOIN(复选框组,"-") 4. 代码实战 首先我们在function包下创建text包…

用户态协议栈01-udp收发

文章目录 用户态协议栈01-udp收发前期准备DPDK初始化开始搓udp协议栈配置dpdk定义udp相关变量接受udp数据&&读取包内容接口层拼接udp数据包完整代码 如何启动实验如何编译使用效果 用户态协议栈01-udp收发 实现用户态协议栈最最简单的就是实现Udp的收发,下…

高性能API云原生网关 APISIX安装与配置指南

Apache APISIX是Apache软件基金会下的顶级项目,由API7.ai开发并捐赠。它是一个高性能的云原生API网关,具有动态、实时等特点。 APISIX网关可作为所有业务的流量入口,为用户提供了丰富的功能,包括动态路由、动态上游、动态证书、A…

将SU模型导入ARCGIS,并获取高度信息,多面体转SHP文件(ARCMAP)

问题:将Sketchup中导出的su模型,导入arcgis并得到面shp文件,进而获取各建筑的高度、面积等信息。 思路: (1)导入arcgis得到多面体 (2)转为面shp文件 (3)计算高度/面积等 1、【3D Analyst工具】【转换】【由文件转出】【导入3D文件】(在此步骤之间,建议先建立一个…

flink学习之旅(二)

目前flink中的资源管理主要是使用的hadoop圈里的yarn,故此需要先搭建hadoop环境并启动yarn和hdfs,由于看到的教程都是集群版,现实是只有1台机器,故此都是使用这台机器安装。 1.下载对应hadoop安装包 https://dlcdn.apache.org/h…

linux centos7.9改dns和ip

vi /etc/sysconfig/network-scripts/ifcfg-ens32 :wq后 重启网络服务 systemctl restart network —————————————————————————— 篇外话题 软件下载 xshell可以从腾讯软件中心下载

dpdk协议栈之udp架构优化

dpdk优势 传统网络架构与 DPDK(Data Plane Development Kit)网络架构之间存在许多区别,而 DPDK 的优势主要体现在以下几个方面: 数据包处理性能:传统网络架构中,网络数据包的处理通常由操作系统的网络协议…

探索便捷办公新选择:ONLYOFFICE 桌面编辑器

目录 引言 1. ONLYOFFICE 桌面编辑器简介 2. 功能特点 2.1 多格式支持 2.2 实时协作编辑 2.3 兼容性与格式保持 2.4 丰富的编辑功能 3. 使用方法 3.1 下载安装 3.2 打开文档 3.3 编辑文档 3.4 保存和共享 4. 注意事项 4.1 版本更新 4.2 网络连接 4.3 安全性 5.…

【电子书】移动开发

整理了一些互联网电子书,推荐给大家 移动开发 Android App开发入门与项目实战.epubAndroid Studio应用开发实战详解.epubAndroid Studio开发实战:从零基础到App上线.epubAndroid 游戏开发大全(第二版).epubAndroid 源码设计模式…

k8s分布式图床(k8s,metricsapi,vue3+ts)

image-manage 文档 warning 注意⚠️ 1. 你需要至少一个mysql数据库 2. 你需要至少一个redis数据库 3. 你需要一个版本至少 kubernetes 1.29的集群(集群可选) ::: 单机部署(docker) # clone the project docker run -p 8080:8080 \-v 你的数据目录:/app\-e CONFIG_ISCLUST…

C语言函数递归

一、什么是递归 递归实际上就是函数自己调用自己。 递归在书写的时候,有2个必要条件: • 递归存在限制条件,当满足这个限制条件的时候,递归便不再继续。 • 每次递归调用之后越来越接近这个限制条件。 在下面的例子中&#xff0…

WPF 附加属性+控件模板,完成自定义控件。建议观看HandyControl源码

文章目录 相关连接前言需要实现的效果附加属性添加附加属性,以Test修改FontSize为例依赖属性使用触发器使用直接操控 结论 控件模板,在HandyControl的基础上面进行修改参考HandyControl的源码控件模板原型控件模板 结论 相关连接 WPF控件模板(6) WPF 附加…

Android之UI Automator框架源码分析(第九篇:UiDevice获取UiAutomation对象的过程分析)

前言 通过UiDevice的构造方法,UiDevice对象持有的几个对象一部分是在构造方法中创建的(初始化),它持有的每个对象都是分析的重点 备注:当前对象持有的对象,它的位置一般在实例变量创建时或者构造方法中&…

ChatGPT国内快速上手指南

ChatGPT简介 ChatGPT是由OpenAI团队研发的自然语言处理模型,该模型在大量的互联网文本数据上进行了预训练,使其具备了深刻的语言理解和生成能力。 GPT拥有上亿个参数,这使得ChatGPT在处理各种语言任务时表现卓越。它的训练使得模型能够理解上…

044-WEB攻防-PHP应用SQL盲注布尔回显延时判断报错处理增删改查方式

044-WEB攻防-PHP应用&SQL盲注&布尔回显&延时判断&报错处理&增删改查方式 #知识点: 1、PHP-MYSQL-SQL注入-方式增删改查 2、PHP-MYSQL-SQL注入-布尔&延迟&报错 3、PHP-MYSQL-SQL注入-数据回显&报错处理 演示案例: ➢PHP…

不懂且不会用循环OB块的plc工程师不是优秀的plc工程师

本章介绍了循环中断OB的功能、与循环中断OB相关的指令、执行过程以及举例说明的内容。 循环中断 OB ● 循环中断 OB 的功能 循环中断 OB 在经过一段固定的时间间隔后执行相应的中断 OB 中的程序。 S7-1500 最多支持 20 个循环中断 OB ,在创建循环中断 OB 时设定…

✅技术社区项目—JWT身份验证

通用的JWT鉴权方案 JWT鉴权流程 基本流程分三步: ● 用户登录成功之后,后端将生成的jwt返回给前端,然后前端将其保存在本地缓存; ● 之后前端与后端的交互时,都将iwt放在请求头中,比如可以将其放在Http的身份认证的请求头 Author…