Linux线程调度bug,Linux线程调度引起的业务问题

一、 问题现象

1.业务组播出向报文偶尔有延迟;

2.单播出向报文平滑

二、 分析及定位

使用wireshark分析了组播出向报文的抓包,报文无丢包,但是IO 输出流量显示有burst和掉坑现象。

波形和抓包文件分析如下图:

d3bc8bfed946a6a7a0460cbc736457dc.png

后来在接收侧抓包,并分析日志,接收方没有出现丢包问题,但是有接收码流不足,导致收包不及时,业务不流畅。

通过在系统内核发包udp_sendmsg函数打点,发现有时候有300ms+没有报文发出,说明发包线程被阻塞。

下面是监控组播出向发包函数udp_sendmsg的打点记录日志:

__dev_xmit_skb:

78      send rate:  9 Mbps

79      send rate:  9 Mbps

80      send rate:  6 Mbps   ##有流量下降

diff_send_time_ms = 346      ##346毫秒无报文发送

81      send rate:  12 Mbps  ##有流量上升

82      send rate:  9 Mbps

83      send rate:  9 Mbps

84      send rate:  8 Mbps

diff_send_time_ms = 316

85      send rate:  7 Mbps   ##被发包线程削峰

86      send rate:  9 Mbps

87      send rate:  9 Mbps

确认系统上有migration实时线程频繁调度,同时发现系统记账功能pacct在系统上写了近70G文件。

b6bac1f8f65b3860ac09a55e1780e7f1.png

其中一台设备上的 pacct文件:

a5c09ecf5c972ba1dff1283d2902628f.png

业务组播发包线程也是实时线程:

63561f91a2e65fc9edf84443c56b3f46.png

关闭psacct服务后,内核migration线程没有再频繁调度,而且发包没有再出现300ms延迟(上图就是去掉psacct服务后的线程调度情况)。

经过几次抓包分析,出向流量很平稳,没有burst情况,业务阻塞现象消失。

关闭方法:

systemctl stop psacct.service

systemctl disable psacct.service

为什么psacct服务引起了migration,进而影响了业务组播发包线程的延迟?

一个猜测是,psacct进程写日志时造成cpu占用太高(当时psacct日志已经达到70G),触发了migration调度,而migration调度又导致业务

ForwardThread实时线程阻塞,引起发包抖动。

三、migration和被阻塞线程ForwardThread调度方式

migration线程简介

为什么存在migration线程?

在计算机系统中,资源使用需要均衡,因此在相同硬件上能够获得较好的星星。在Linux内核系统中,使用一些迁移内核线程来做这些事情。

内核怎么创建migration线程?

migration线程相关结构定义:

static struct smp_hotplug_thread cpu_stop_threads = {

.store            = &cpu_stopper.thread,

.thread_should_run    = cpu_stop_should_run,

.thread_fn        = cpu_stopper_thread,

.thread_comm        = "migration/%u",

.create            = cpu_stop_create,

.setup            = cpu_stop_unpark,

.park            = cpu_stop_park,

.pre_unpark        = cpu_stop_unpark,

.selfparking        = true,

};

migration线程创建过程:

static int __init cpu_stop_init(void)

-->BUG_ON(smpboot_register_percpu_thread(&cpu_stop_threads));

1)__smpboot_create_thread

## kthread_create_on_cpu 创建线程调度优先级为0,调度策略为SCHED_NORMAL

tsk = kthread_create_on_cpu(smpboot_thread_fn, td, cpu, ht->thread_comm);  //register smpboot_thread_fn

-->kthread_create_on_node

-->sched_setscheduler_nocheck

2)## cpu_stop_create 设置调度优先级为MAX_RT_PRIO - 1(99),调度策略为SCHED_FIFO

ht->create(cpu); ## cpu_stop_create

系统中migration线程信息:

68772ea3fddf57866e7170915eb76d47.png

297e03f860baba4cad327f19a7877255.png

业务组播发包线程调度方式:

在我们的业务代码中,通过以下接口设置业务发包线程调度策略和优先级:

param.sched_priority = sched_get_priority_max(SCHED_FIFO)  ;   /* 这个优先级为99 */

ret = pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);

批注: 使用pthread_setschedparam函数设置可能会出现EPERM错误,这个又是另外一个问题了,后面单独开篇:)

系统中业务发包线程信息:

99493b0185ea1d25cce4a9e6862894d8.png

参考资料:

【migration介绍】https://www.systutorials.com/239971/migration-thread-works-inside-linux-kernel/

【Linux调度优先级】https://superuser.com/questions/203657/difference-between-nice-value-and-priority-in-the-top-output

标签:thread,stop,调度,send,线程,migration,Linux,cpu

来源: https://www.cnblogs.com/smith9527/p/12168508.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值