kubeskoop icon indicating copy to clipboard operation
kubeskoop copied to clipboard

如何理解 SOCKETLAT_READSLOW

Open wangqiongkaka opened this issue 1 year ago • 3 comments

我们有一个访问redis的请求,redis有质量监控,每次get的p99时间基本上在1ms左右,但是 SOCKETLAT_READSLOW 有大量的大于100ms的 看代码sock_receive的时候会记录一个时间,然后对比socket_read之间的时间差,不知道我理解的对不对 image

wangqiongkaka avatar Jul 11 '24 03:07 wangqiongkaka

是的,这种就是是kernel处理好了,应用层读的慢了 一般遇到这个问题的原因主要是:

  • 应用容器的CPU限流了,可以关注Pod的cpu throttle情况
  • 应用本身的配置或者实现问题,比如java的full gc, 或者线程池满了之类的导致无法及时处理

BSWANG avatar Jul 15 '24 02:07 BSWANG

是的,这种就是是kernel处理好了,应用层读的慢了 一般遇到这个问题的原因主要是:

  • 应用容器的CPU限流了,可以关注Pod的cpu throttle情况
  • 应用本身的配置或者实现问题,比如java的full gc, 或者线程池满了之类的导致无法及时处理

这个地方的实现应该是有问题,并不是所有的包都会在调用 sock_def_readable 后再调用 tcp_cleanup_rbuf。调用 sock_def_readable 后会记录一个 lastreceive,假如这个时候系统没有再接收新的包,但是可能存在调用 tcp_cleanup_rbuf 的情况,这个时候 latency = now - ski->lastreceive 就会不停的增大。类似以下的代码实现

        readTimeout := 2*time.Second

        buffer := make([]byte, 512)

        for {
                err = conn.SetReadDeadline(time.Now().Add(readTimeout)) // timeout
                if err != nil {
                        log.Println("setReadDeadline failed:", err)
                }

                n, err := conn.Read(buffer)
                if err != nil {
                        log.Println("Read failed:", err)
                        //break
                }

                log.Println("count:", n, "msg:", string(buffer))
        }

客户端每隔2s就会去进行一次 Read ,但是服务端并没有往 buffer 写数据,这个时候每隔2s就会有一个event,并且 latency 值会不断的累加

int sock_read(struct pt_regs *ctx)
        {
                struct sock * sk = (struct sock *)PT_REGS_PARM1(ctx);
                int copied = (int)PT_REGS_PARM2(ctx);
                struct sklat_key_t * ski;
                ski = bpf_map_lookup_elem(&insp_sklat_entry, &sk);
                if (ski) {
                u64 now = bpf_ktime_get_ns();
                    if (ski->lastreceive > 0) {
                        u64 latency;
                        latency = now - ski->lastreceive;
                        ski->lastreceive = 0;
                ......
        }

每次调用 tcp_cleanup_rbuf 以后增加一个 ski->lastreceive = 0 的操作会不会更好?同理调用 tcp_write_xmit 也是一样的

wangqiongkaka avatar Aug 12 '24 06:08 wangqiongkaka

这个问题没有进展吗?说的有道理啊

JasperWey avatar Apr 07 '25 06:04 JasperWey