内存回收导致关键业务抖动案例分析-论云原生OS内存QoS保障

本文分析了一起由于nss库bug导致的云原生场景中内存回收问题,引发了关键业务的系统抖动。通过perf工具捕获现场,发现dentry_lru_lock锁竞争是问题根源。解决方案包括升级nss服务或设置环境变量规避。同时,讨论了内核锁优化、negative dentry限制以及内存回收机制的局限,强调云原生OS需要深度定制以应对复杂场景。
摘要由CSDN通过智能技术生成

蒋彪,腾讯云高级工程师,10+年专注于操作系统相关技术,Linux内核资深发烧友。目前负责腾讯云原生OS的研发,以及OS/虚拟化的性能优化工作。

## 导语

云原生场景,相比于传统的IDC场景,业务更加复杂多样,而原生 Linux kernel 在面对云原生的各种复杂场景时,时常显得有些力不从心。本文基于一个腾讯云原生场景中的一个实际案例,展现针对类似问题的一些排查思路,并希望借此透视Linux kernel的相关底层逻辑以及可能的优化方向。

## 背景

腾讯云客户某关键业务容器所在节点,偶发CPU sys(内核态CPU占用)冲高的问题,导致业务抖动,复现无规律。节点使用内核为upstream 3.x版本。

## 现象

在业务负载正常的情况下,监控可见明显的CPU占用率毛刺,最高可达100%,同时节点load飙升,此时业务会随之出现抖动。

![](https://main.qcloudimg.com/raw/3b77e017c01469f86363f1883f00dcdb.png)

## 捕获数据

### 思路

故障现象为CPU sys冲高,即CPU在内核态持续运行导致,分析思路很简单,需要确认sys冲高时,具体的执行上下文信息,可以是堆栈,也可以是热点。

**难点:**
由于故障出现随机,持续时间比较短(秒级),而且由于是内核态CPU冲高,当故障复现时,常规排查工具无法得到调度运行,登录终端也会hung住(由于无法正常调度),所以常规监控(通常粒度为分钟级)和排查工具均无法及时抓到现场数据。

### 具体操作

#### 秒级监控

通过部署秒级监控(基于atop),在故障复现时能抓到故障发生时的系统级别的上下文信息,示例如下:
![](https://main.qcloudimg.com/raw/ff5d0054f633b2ce910c7fafe601db12.jpg)

从图中我们可以看到如下现象:

1. sys很高,usr比较低
2. 触发了页面回收(PAG行),且非常频繁
3. 比如ps之类的进程普遍内核态CPU使用率较高,而用户态CPU使用率较低,且处于退出状态

至此,抓到了系统级别的上下文信息,可以看到故障当时,系统中正在运行的、CPU占用较高的进程和状态,也有一些系统级别的统计信息,但仍无从知晓故障当时,sys具体消耗在了什么地方,需要通过其他方法/工具继续抓现场。

#### 故障现场

如前面所说,这里说的**现场**,可以是故障当时的瞬时堆栈信息,也可以是热点信息。
对于堆栈的采集,直接能想到的简单方式:

1. pstack
2. cat /proc/<pid>/stack

当然这两种方式都依赖:

1. 故障当时CPU占用高的进程的pid
2. 故障时采集进程能及时执行,并得到及时调度、处理

显然这些对于当前的问题来说,都是难以操作的。

对于热点的采集,最直接的方式就是perf工具,简单、直接、易用。但也存在问题:

1. 开销较大,难以常态化部署;如果常态化部署,采集数据量巨大,解析困难
2. 故障时不能保证能及时触发执行

perf本质上是通过pmu硬件进行周期性采样,实现时采用NMI(x86)进行采样,所以,一旦触发采集,就不会受到调度、中断、软中断等因素的干扰。但由于执行perf命令的动作本身必须是在进程上下文中触发(通过命令行、程序等),所以在故障发生时,由于内核态CPU使用率较高,并不能保证perf命令执行的进程能得到正常调度,从而及时采样。

因此针对此问题的热点采集,必须提前部署(常态化部署)。通过两种方式可解决(缓解)前面提到的开销大和数据解析困难的问题:

1. 降低perf采样频率,通常降低到99次/s,实测对真实业务影响可控
2. Perf数据切片。通过对perf采集的数据按时间段进行切片,结合云监控中的故障时间点(段),可以准确定位到相应的数据片,然后做针对性的统计分析。

具体方法:
采集:

```
`.``/perf` `record -F99 -g -a`
```

分析:

```
#查看header里面的captured on时间,应该表示结束时间,time of last sample最后采集时间戳,单位是秒,可往前追溯现场时间
./perf report --header-only
#根据时间戳索引
./perf report --time start_tsc,end_tsc
```

按此思路,通过提前部署perf工具采集到了一个**现场**,热点分析如下:

![](https://main.qcloudimg.com/raw/1b0d43937b70cf3058b596ffa6b3e8bc.png)

可以看到,主要的热点在于 shrink_dentry_list 中的一把 spinlock。

## 分析

### 现场分析

根据 perf 的结果,我们找到内核中的热点函数 dentry_lru_del,简单看下代码:

```
// dentry_lru_del()函数:
static void dentry_lru_del(struct dentry *dentry) {
    if (!list_empty(&dentry->d_lru)) {
        spin_lock(&dcache_lru_lock);
        __dentry_lru_del(dentry);
        spin_unlock(&dcache_lru_lock);
    }
}
```

函数中使用到的 spinlock 为 dentry_lru_lock,在3.x内核代码中,这是一把超大锁(全局锁

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值