【TCP/IP】【调试】丢包、流不通、错包等问题查证手段系列之一——日志方式

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 【TCP/IP】【调试】丢包、流不通、错包等问题查证手段系列之一——日志方式

前言


在进行TCP/IP相关的开发过程中,经常需要查证丢包、错包、流不通等问题。由于TCP/IP转发面涉及软件和硬件、并且软件流程上函数多、分支多,无论是增加打印或是分析流程,都比较困难。


本系列文章会将常用的定位手段,做一简单的总结和说明,各位可根据问题的情况,选取一种或结合使用。


日志方式简介


  • 虽然打印这种方式比较Low,但在有的情况下反而是最直接和有效的方式,有的情况下更是开发人员的杀手锏。


直接打印报文


  • 直接在需要的地方调用类似下面的print_skb的函数即可。


void print_skb(struct sk_buff *skb)
{
    if (skb) {
        char *buf = skb->data;
        int len = skb->len;
        int i = 0;
        printk("[%s:%d]Packet length = %#4x\n", __FUNCTION__, __LINE__, len);
        for (i = 0; i < len; i++){
            if (i % 16 == 0) printk("%#4.4x", i);
            if (i % 2 == 0) printk(" ");
            printk("%2.2x", ((unsigned char *)buf)[i]);
            if (i % 16 == 15) printk("\n");
        }
        printk("\n\n");
    }
}


值得一提的是,在有的内核版本中,上述代码打印不全,skb->data需要换成skb->mac_header。


另外,这种打印方式,如报文太多,会刷屏,可能将系统打宕机。


条件打印


  • 根据报文中特定字段进行打印,需要在skb结构体中增加一个字段:


struct sk_buff {
  unsigned int dbg_flag;
}


具体在某个位置,首先判断某skb是否需要被打印,比如要跟踪DHCP报文,则在某个入口或点的位置识别DHCP报文并将该标志位置上,具体可参考下面的代码段:


struct ethhdr *mh = (struct ethhdr *)(skb->mac_header);
if(mh->h_proto != htons(ETH_P_IP)) {
    return;
}
struct iphdr *iph = (struct iphdr *)ip_hdr(skb);
if(iph && iph->protocol != IPPROTO_UDP) {
    return ;
}
    // ip header --> iph->ihl*4;
struct udphdr *udph = (struct udphdr *) ((char *)iph + iph->ihl*4);
if(udph && udph->source == htons(68) && udph->dest == htons(67)) {
    skb->dbg_flag = 1;


之后,在后续其他点上,就可以直接根据这个flag来控制打印:


if (1 == skb->dbg_flag) {
    print_skb(skb);
}


开关控制打印


  • 通过某proc文件修改内核某变量,然后根据该变量来控制打印。


echo 1>/proc/net/logctl //假设logctl文件对应g_logctl变量


代码中的具体控制:


if (1 == g_logctl) {
        print_skb(skb);
    }


ratelimit限速打印


  • 限速判断函数可以用net_ratelimit或printk_ratelimit;


 if (net_ratelimit()) {
     print_skb(skb);
 }
  if (printk_ratelimit()) {
     print_skb(skb);
 }


这种打印,有个缺陷,有可能会被限速抑制掉而打印不出来,此时会有下面这种打印出现:


__ratelimit: 250 callbacks suppressed


具体的限速参数,可使用下面方式修改:


[qxhgd@localhost ~]$ cat /proc/sys/kernel/printk_ratelimit
5
[qxhgd@localhost ~]$ cat /proc/sys/kernel/printk_ratelimit_burst
10
# printk_ratelimit默认允许在5s内最多打印10条消息出来: /proc/sys/kernel/printk_ratelimit (多长时间)和 /proc/sys/kernel/printk_ratelimit_burst (在上述时间段内最多允许的消息数量)


自定义限速打印


  • 也可以根据需要,使用系统时间来自行控制打印,比如下面代码段可控制每秒最多打印一个报文:


unsigned long g_lastTime = 0; #全局变量
if (jiffies - g_lastTime > 1 * HZ)  {
    print_skb(skb);
    g_lastTime = jiffies;
}
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
5月前
|
消息中间件 存储 Java
手动实现 Spring Boot 日志链路追踪:提升调试效率的利器
【8月更文挑战第8天】在复杂的分布式系统中,日志是诊断问题、追踪系统行为的重要工具。然而,随着微服务架构的普及,服务间的调用链路错综复杂,传统的日志记录方式往往难以快速定位问题源头。今天,我们将探讨如何在不依赖外部组件(如Zipkin、Sleuth等)的情况下,手动实现Spring Boot应用的日志链路追踪,让日志定位更加便捷高效。
215 1
|
1月前
|
监控 应用服务中间件 定位技术
要统计Nginx的客户端IP,可以通过分析Nginx的访问日志文件来实现
要统计Nginx的客户端IP,可以通过分析Nginx的访问日志文件来实现
|
1月前
|
存储 Prometheus 监控
Docker容器内进行应用调试与故障排除的方法与技巧,包括使用日志、进入容器检查、利用监控工具及检查配置等,旨在帮助用户有效应对应用部署中的挑战,确保应用稳定运行
本文深入探讨了在Docker容器内进行应用调试与故障排除的方法与技巧,包括使用日志、进入容器检查、利用监控工具及检查配置等,旨在帮助用户有效应对应用部署中的挑战,确保应用稳定运行。
42 5
|
2月前
|
前端开发 数据处理 Android开发
Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍
本文深入探讨了Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍,以及具体操作步骤、常见问题解决、高级调试技巧、团队协作中的调试应用和未来发展趋势,旨在帮助开发者提高调试效率,提升应用质量。
60 8
|
3月前
|
Java 程序员 应用服务中间件
「测试线排查的一些经验-中篇」&& 调试日志实战
「测试线排查的一些经验-中篇」&& 调试日志实战
32 1
「测试线排查的一些经验-中篇」&& 调试日志实战
|
3月前
|
缓存 Linux 编译器
【C++】CentOS环境搭建-安装log4cplus日志组件包及报错解决方案
通过上述步骤,您应该能够在CentOS环境中成功安装并使用log4cplus日志组件。面对任何安装或使用过程中出现的问题,仔细检查错误信息,对照提供的解决方案进行调整,通常都能找到合适的解决之道。log4cplus的强大功能将为您的项目提供灵活、高效的日志管理方案,助力软件开发与维护。
87 0
|
5月前
|
JavaScript Java API
Java日志通关(二) - Slf4j+Logback 整合及排包
作者日常在与其他同学合作时,经常发现不合理的日志配置以及五花八门的日志记录方式,后续作者打算在团队内做一次Java日志的分享,本文是整理出的系列文章第二篇。
|
5月前
|
应用服务中间件 Linux nginx
在Linux中,如何统计ip访问情况?分析 nginx 访问日志?如何找出访问页面数量在前十位的ip?
在Linux中,如何统计ip访问情况?分析 nginx 访问日志?如何找出访问页面数量在前十位的ip?
|
5月前
|
XML Java 数据库
"揭秘!Spring Boot日志链路追踪大法,让你的调试之路畅通无阻,效率飙升,问题无所遁形!"
【8月更文挑战第11天】在微服务架构中,请求可能跨越多个服务与组件,传统日志记录难以全局追踪问题。本文以电商系统为例,介绍如何手动实现Spring Boot应用的日志链路追踪。通过为每个请求生成唯一追踪ID并贯穿全链路,在服务间传递该ID,并在日志中记录,即使日志分散也能通过ID串联。提供了实现这一机制所需的关键代码片段,包括使用过滤器设置追踪ID、业务代码中的日志记录及Logback配置。此方案显著提升了问题定位的效率,适用于基于Spring Boot构建的微服务环境。
123 4
|
5月前
|
SQL 数据库 Java
Hibernate 日志记录竟藏着这些秘密?快来一探究竟,解锁调试与监控最佳实践
【8月更文挑战第31天】在软件开发中,日志记录对调试和监控至关重要。使用持久化框架 Hibernate 时,合理配置日志可帮助理解其内部机制并优化性能。首先,需选择合适的日志框架,如 Log4j 或 Logback,并配置日志级别;理解 Hibernate 的多级日志,如 DEBUG 和 ERROR,以适应不同开发阶段需求;利用 Hibernate 统计功能监测数据库交互情况;记录自定义日志以跟踪业务逻辑;定期审查和清理日志避免占用过多磁盘空间。综上,有效日志记录能显著提升 Hibernate 应用的性能和稳定性。
57 0