首页 > 其他分享 >tcp缓存引起的日志丢失

tcp缓存引起的日志丢失

时间:2024-01-04 12:03:38浏览次数:35  
标签:newSize 缓存 scanner tcp maxTokenSize proxy 日志


背景

logstash从数据源拉取日志,然后通过tcp插件发送到proxy进程中。在业务侧发现日志量明显少了,所以有了这一次的问题排查。

tcp缓存引起的日志丢失_缓存

问题排查定位

首先从logstash侧开始检查。我们先看logstash的日志,没有明显的报错信息。

然后再查看logstash管道的状态。可以很明显的看到,在output管道中,in远远大于out,也就是logstash拉取的日志已经到了output管道,但是无法输出出去,并且duration_in_millis时间很长,这个代表着发出去的速率很慢,这是什么原因呢?

curl -XGET 'localhost:9600/_node/stats/pipelines/azure_event_hubs?pretty'

{
    ...
"outputs" : [ {
        "id" : "99b12e190d297be5d6113d04cf10089a3dccbaef7eed0cc41515e8e5af5f4595",
        "name" : "tcp",
        "events" : {
        "in" : 341,
        "out" : 69,
        "duration_in_millis" : 519709
        }
    } 
}

要么是发送方的原因,要么是接收方的原因。我先从发送方进行排查,我在output管道中,除了tcp插件外,还添加了stdout插件,也就是日志来了除了会通过tcp发送外,还会打印在标准输出中。

output {

    tcp {
        ...
    }

    stdout {}

}

然后等待一段时间,然后再查看该管道的信息,stdout插件的in和out完全相等,但tcp插件in和out还是相差甚大,也就是output管道应该没问题。

我再假设proxy端有问题。日志是可以从logstash端发送到proxy端的,只是很慢,并且还有其他数据源也在往proxy端发送日志,也没有这个问题,所以我突然想到,该数据源的日志很大,会不会是这个原因导致的呢?

我从上面标准输出中抓了一条日志出来,134k大小,然后我手动的用nc命令将日志发送到proxy,因为日志很大,我是将日志写入到文件,然后再用管道的方式发送的

cat test.txt | nc

通过查看proxy的日志发现,其根本没有收到该条日志。那么问题原因找到了,就是因为日志太大,导致日志发生了丢失。

代码排查

proxy服务的是golang写的,通过查看代码,这里使用了bufio.NewScanner来循环读取连接中的数据。

scanner := bufio.NewScanner(conn)

	for scanner.Scan() {
		// 处理数据
		msg := scanner.Text()
        ...

查看NewScanner方法可以看到有一个maxTokenSize参数,然后用的默认值MaxScanTokenSize

func NewScanner(r io.Reader) *Scanner {
	return &Scanner{
		r:            r,
		split:        ScanLines,
		maxTokenSize: MaxScanTokenSize,
	}
}

再跳转,有一个初始化缓存大小startBufSize为4k和最大的缓存大小MaxScanTokenSize为64k。但是我们的日志大小为134k,已经大于最大大小了,所以无法接收到该日志,也就是因为这个原因导致了日志发生了丢失。

const (
	MaxScanTokenSize = 64 * 1024

	startBufSize = 4096
)

我们再看下Scan方法,有一段代码如下,如果拿到的数据的大小大于maxTokenSize,则会使用s.setErr(ErrTooLong)记录错误,然后返回false

func (s *Scanner) Scan() bool {

    ..
    const maxInt = int(^uint(0) >> 1)
    if len(s.buf) >= s.maxTokenSize || len(s.buf) > maxInt/2 {
        s.setErr(ErrTooLong)
        return false
    }
    newSize := len(s.buf) * 2
    if newSize == 0 {
        newSize = startBufSize
    }
    if newSize > s.maxTokenSize {
        newSize = s.maxTokenSize
    }
    newBuf := make([]byte, newSize)
    copy(newBuf, s.buf[s.start:s.end])
    ...

}

但是我们在业务代码中,并没有判断该错误,也就是如果Scan方法虽然返回了false,循环结束了,但是并没有任何错误信息。也就是无法发现该问题。

解决方法

  1. 将TCP的最大缓存大小修改为配置文件可配置的,这样如果日志很大,可以修改配置增大缓存上限。库中有提供Buffer方法来设置该上限。
  2. 在Scan发生错误时,打印错误日志,代码如下:
scanner := bufio.NewScanner(conn)

for scanner.Scan() {
    // 处理数据
    msg := scanner.Text()
    ...

if err := scanner.Err(); err != nil {
    log.Errorf("扫描输入时发生错误:%s", err)
}

总结

  1. 要提高自己的排查的手段,熟悉组件提供的排查机制,让你事半功倍。
  2. 每一个提供的参数都至关重要,所以我们都需要有一定的理解,可以减少BUG的发生

欢迎关注,互相学习,共同进步~

我的个人博客 公众号:编程黑洞


标签:newSize,缓存,scanner,tcp,maxTokenSize,proxy,日志
From: https://blog.51cto.com/zhengwenfeng/9098421

相关文章

  • Linux中tcp连接数过多会造成什么影响?
    TCP是Internet协议族中的一种连接方式,在Linux系统中TCP连接数限制是非常重要的参数,不同版本的Linux内核TCP连接数限制的默认值也不同。那么Linux中tcp连接数过多会造成什么影响?具体请看下文。TCP连接数过多可能导致程序挂掉。当一个程序处理大量的TCP连接时,它可能会消耗系......
  • Linux中tcp连接数过多会造成什么影响?
    TCP是Internet协议族中的一种连接方式,在Linux系统中TCP连接数限制是非常重要的参数,不同版本的Linux内核TCP连接数限制的默认值也不同。那么Linux中tcp连接数过多会造成什么影响?具体请看下文。TCP连接数过多可能导致程序挂掉。当一个程序处理大量的TCP连接时,它可能会消耗系......
  • SpringBoot+modbus4j实现ModebusTCP通讯读取数据
    场景Windows上ModbusTCP模拟Master与Slave工具的使用:Windows上ModbusTCP模拟Master与Slave工具的使用ModebusTCPModbus由MODICON公司于1979年开发,是一种工业现场总线协议标准。1996年施耐德公司推出基于以太网TCP/IP的Modbus协议:ModbusTCP。Modbus协议是一项应用层报文传输协议,包......
  • Windows上ModbusTCP模拟Master与Slave工具的使用
    场景ModbusSlave与ModbusPoll主从设备模拟软件与ConfigureVirtualSerial串口模拟软件使用:ModebusSlave与ModbusPoll主从设备模拟软件与ConfigureVirtualSerial串口模拟软件使用_modbuspoll激活数据对接协议为ModbusTCP,本地开发需要使用模拟工具调试。使用ModbusSla......
  • DockerCompose中重启某个服务时提示: (iptables failed: iptables --wait -t nat -A D
    场景DockerCompose修改某个服务的配置(添加或编辑端口号映射)后如何重启单个服务使其生效:DockerCompose修改某个服务的配置(添加或编辑端口号映射)后如何重启单个服务使其生效_docker-compose修改端口映射基于docker-compose的方式,如果只是要单纯的重启某个服务,则可以通过docker-c......
  • VMware vRealize Log Insight 8.6 下载 - 智能日志记录和分析
    作者:gc,主页:www.sysin.org概述vRealizeLoglnsight提供了高度可扩展的异构日志管理功能,它具有多个可在其中执行操作的直观仪表盘、完善的分析功能和范围更广的第三方延展性。它还能够跨物理、虚拟和云计算环境提供深入的运维洞察信息并加快故障排除速度。VMwarevRealizeLogInsi......
  • 深入了解Apache 日志,Apache 日志分析工具
    ApacheWeb服务器在企业中广泛用于托管其网站和Web应用程序,Apache服务器生成的原始日志提供有关Apache服务器托管的网站如何处理用户请求以及访问您的网站时经常遇到的错误的重要信息。什么是Apache日志Apache日志包含ApacheWeb服务器处理的所有事件的记录-从各种计......
  • RHEL CentOS Debian Ubuntu 如何刷新 DNS 缓存
    RHELCentOSDebianUbuntu如何刷新DNS缓存全文:如何刷新DNS缓存(macOS,Linux,Windows)UnixLinuxWindows如何刷新DNS缓存(macOS,FreeBSD,RHEL,CentOS,Debian,Ubuntu,Windows)作者主页:sysin.org刷新或者清除DNS缓存,通常是因为有过时的DNS记录,需要立刻从服务......
  • VMware vRealize Log Insight 8.3 发布 - 智能日志记录和分析
    VMwarevRealizeLogInsight8.3发布-智能日志记录和分析VMwarevRealizeLogInsight8.3概述vRealizeLoglnsight提供了高度可扩展的异构日志管理功能,它具有多个可在其中执行操作的直观仪表盘、完善的分析功能和范围更广的第三方延展性。它还能够跨物理、虚拟和云计算环境......
  • VMware vRealize Log Insight 8.4 发布 - 智能日志记录和分析
    概述vRealizeLoglnsight提供了高度可扩展的异构日志管理功能,它具有多个可在其中执行操作的直观仪表盘、完善的分析功能和范围更广的第三方延展性。它还能够跨物理、虚拟和云计算环境提供深入的运维洞察信息并加快故障排除速度。VMwarevRealizeLogInsight提供集中式日志管理......