8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

当目标进程繁忙时,Pprof 会卡住很长一段时间

vinuZachariah 2月前

69 0

我尝试使用以下命令在我的 ubuntu 22.04 上运行一个进程的 pprof:go tool pprof http://localhost:9091/debug/pprof/profile,当目标进程以轻量级运行时

我尝试使用以下命令获取在我的 ubuntu 22.04 上运行的一个进程的 pprof: go tool pprof http://localhost:9091/debug/pprof/profile

好吧,当目标进程在轻负载下运行时,这个命令可以给我一个有效的 pprof 结果,但这毫无意义。

当目标进程运行繁忙时,正如我所料,消耗了大约 200% 的 CPU。 上面的命令将卡住并且根本无法结束。

ENV:unbuntu 22.04go:1.22.3pprof:最新安装(go install github.com/google/pprof@latest)

我尝试获取卡住的 pprof 的堆栈,如下所示:

#0  runtime.futex () at /usr/local/go/src/runtime/sys_linux_amd64.s:558
#1  0x0000000000439bf0 in runtime.futexsleep (addr=0xfffffffffffffe00, val=0, ns=4671651) at /usr/local/go/src/runtime/os_linux.go:69
#2  0x0000000000411ac7 in runtime.notesleep (n=0xd2c5c0 <runtime.m0+320>) at /usr/local/go/src/runtime/lock_futex.go:170
#3  0x0000000000445133 in runtime.mPark () at /usr/local/go/src/runtime/proc.go:1761
#4  runtime.stoplockedm () at /usr/local/go/src/runtime/proc.go:3026
#5  0x000000000044745a in runtime.schedule () at /usr/local/go/src/runtime/proc.go:3847
#6  0x0000000000447aac in runtime.park_m (gp=0xc0001be380) at /usr/local/go/src/runtime/proc.go:4036
#7  0x0000000000470a6e in runtime.mcall () at /usr/local/go/src/runtime/asm_amd64.s:458
#8  0x00007fff5315c688 in ?? ()
#9  0x00000000004753ff in runtime.newproc (fn=0x47096f <runtime.rt0_go+303>) at <autogenerated>:1
#10 0x00000000004709e5 in runtime.mstart () at /usr/local/go/src/runtime/asm_amd64.s:394
#11 0x000000000047096f in runtime.rt0_go () at /usr/local/go/src/runtime/asm_amd64.s:358
#12 0x0000000000000002 in ?? ()
#13 0x00007fff5315c6d8 in ?? ()
#14 0x00007fff5315c6d0 in ?? ()
#15 0x0000000000000002 in ?? ()
#16 0x00007fff5315c6d8 in ?? ()
#17 0x0000777de028b2ca in _dl_start_user () from /lib64/ld-linux-x86-64.so.2
#18 0x0000000000000002 in ?? ()
#19 0x00007fff5315da7b in ?? ()
#20 0x00007fff5315daa4 in ?? ()
#21 0x0000000000000000 in ?? ()

看起来 pprof 正在按照计划休眠,很难知道原因。

我确信这个卡住和工作负载有关,因为当通过在客户端设置睡眠时间(例如“sleep(10)”)来调整工作负载时,pprof 也会卡住一段时间,但最终可以返回结果。

有人有处理过此类案件吗?

帖子版权声明 1、本帖标题:当目标进程繁忙时,Pprof 会卡住很长一段时间
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由vinuZachariah在本站《go》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 我的服务器代码在 golangpackage mainimport 中(\'fmt\' \'log\' \'net/http\' \'github.com/rs/cors\')func main() { mux := http.NewServeMux();...

    我的服务器代码用 golang 编写

    package main
    
    import (
        "fmt"
        "log"
        "net/http"
    
        "github.com/rs/cors"
    )
    
    func main() {
        mux := http.NewServeMux();
    
        mux.HandleFunc("/sse" , handleSse)
    
        c  := cors.New(cors.Options{
                AllowedOrigins:   []string{"*"},
                AllowedMethods:   []string{http.MethodGet, http.MethodPost,
                            http.MethodDelete , http.MethodPut},
                AllowCredentials: true,
            })
    
        handler := c.Handler(mux)
    
        log.Fatal(http.ListenAndServe(":6969" , handler))
    }
    
    func handleSse(w http.ResponseWriter , r * http.Request){
    
        w.Header().Set("Content-type","text/event-stream")
        w.Header().Set("Cache-Control","no-cache")
        w.Header().Set("Connection","keep-alive")
    
        f , ok := w.(http.Flusher);
        if !ok{
        http.Error( w , "SSE not supported" ,
            http.StatusBadRequest)
        return;
        }
    
        fmt.Fprintf(w,"data:%v\n\n","sample data");
        f.Flush();
    }
    

    客户端代码

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <title>SSE</title>
      </head>
      <body>
        SSE running
        <script>
        const event = new EventSource("http://localhost:6969/sse");
        event.onmessage = () =>{
            console.log("this dude is slow");
        };
        </script>
      </body>
    </html>
    
    

    我遇到的问题是,在网络选项卡中,新的文本流或响应在 5.4 秒后出现。我希望服务器每 2 秒发送一次响应,我尝试在服务器代码中使用无限 for 循环,如某些教程中所示,但它不起作用

    编辑:for 循环处理程序函数

    
    func handleSse(w http.ResponseWriter , r * http.Request){
    
        w.Header().Set("Content-type","text/event-stream")
        w.Header().Set("Cache-Control","no-cache")
        w.Header().Set("Connection","keep-alive")
        w.WriteHeader(http.StatusOK)
    
        f , ok := w.(http.Flusher);
        if !ok{
        http.Error( w , "SSE not supported , IE6 bruh" ,
            http.StatusBadRequest)
        return;
        }
    
        for i := 0 ; i < 10 ; i++{
            fmt.Fprintln(w,"retry : 1000"); //This line also doesnot help
            fmt.Fprintf(w,"data :%v\n\n","Sorry");
            f.Flush();
        //time.Sleep(1 * time.Second) //This line increase delay to 25 secs
        }
    }
    
  • \'我尝试过在服务器代码中无限循环\' - 向我们展示这一点。您当前的代码将发送一条消息,然后关闭连接(因此消息之间的延迟是

  • 我尝试提供重新连接时间,但无济于事。延迟仍为 5 秒,我还编辑了问题并添加了循环代码。

  • tpko 2月前 0 只看Ta
    引用 5

    间距很重要 - fmt.Fprintf(w,"data :%v\n\n","Sorry"); 不起作用;需要 fmt.Fprintf(w, "data:%v\n\n", "Sorry") .

    以下是一个实际示例;它将发送 10 条消息,然后断开连接。由于它还设置了 retry: 10000 (即重试 10000ms 10s ,浏览器将在 10 秒后重新连接(并每隔一秒接收另外 10 条消息)。请注意,我在消息中添加了时间戳(使输出更清晰,因为浏览器倾向于合并相同的输出行)。

    package main
    
    import (
        "fmt"
        "log"
        "net/http"
        "time"
    
        "github.com/rs/cors"
    )
    
    func main() {
        mux := http.NewServeMux()
    
        mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
            w.Write([]byte(`<!DOCTYPE html>
    <html lang="en">
      <head>
        <title>SSE</title>
      </head>
      <body>
        SSE running
        <script>
        const event = new EventSource("http://localhost:6969/sse");
        event.onmessage = () =>{
            console.log("this dude is slow");
        };
        </script>
      </body>
    </html>
    `))
        })
    
        mux.HandleFunc("/sse", handleSse)
    
        c := cors.New(cors.Options{
            AllowedOrigins: []string{"*"},
            AllowedMethods: []string{http.MethodGet, http.MethodPost,
                http.MethodDelete, http.MethodPut},
            AllowCredentials: true,
        })
    
        handler := c.Handler(mux)
    
        log.Fatal(http.ListenAndServe(":6969", handler))
    }
    
    func handleSse(w http.ResponseWriter, r *http.Request) {
    
        w.Header().Set("Content-type", "text/event-stream")
        w.Header().Set("Cache-Control", "no-cache")
        w.Header().Set("Connection", "keep-alive")
        w.WriteHeader(http.StatusOK)
    
        f, ok := w.(http.Flusher)
        if !ok {
            http.Error(w, "SSE not supported , IE6 bruh",
                http.StatusBadRequest)
            return
        }
    
        for i := 0; i < 10; i++ {
            fmt.Fprintln(w, "retry: 10000") // This means that after the connection drops the browser will wait 10 seconds before reconnecting
            fmt.Fprintf(w, "data:%v\n\n", "Sorry")
            f.Flush()
            time.Sleep(1 * time.Second) // This means a message will be sent every second (until 10 have been sent when the connection will drop)
        }
    }
    

    在实际系统中,处理程序( handleSse 在本例中)可能仅在写入时收到错误时才会退出,否则只要程序正在运行,它就会一直处于活动状态。这样的处理程序将从某个地方(可能是通过通道)接收数据,并将其发送到浏览器。

    请注意,我最初建议添加的目的 fmt.Fprintln(w, "retry: 1000") 是为了让事情更清楚。使用您的初始代码,浏览器正在连接,接收一条消息(之后服务器断开连接),然后在 5 秒后重新连接(接收另一条消息...)。

  • 我正在使用 Golang 与 Kafka 消费者合作。之前有一个消费者代码库,它在消费者组为 consumer-1 的服务器上运行,并且该消费者中有大量数据,以至于

    我正在使用 Golang 与 Kafka 消费者合作。之前有一个消费者代码库,它在带有消费者组的服务器上运行 consumer-1 ,并且该消费者中有很多数据,因此读取工作正常。但现在我正在创建一个具有相同组 ID 的新消费者,并在配置下进行了一些调整,但它没有收到消息。

    代码库

      reader := kafka.NewReader(kafka.ReaderConfig{
                Brokers:          []string{config.KAFKA.Broker},
                Topic:            newTopic,
                MaxBytes:         10485760,
                GroupID:          "consumer-1",
                MaxWait:          time.Duration(2 * time.Second),
                ReadBatchTimeout: time.Duration(2 * time.Second),
                QueueCapacity:    10000,
                // Dialer:           dailer,
            })
    

    我正在使用的库

    "github.com/segmentio/kafka-go"
    

    这是我在之前的代码中所做的配置,是一样的。为什么这不起作用?

  • 除了 @Britis 的回答,每 2 秒运行无限次。我正在使用 golang ticker 并使用 context 在客户端断开连接或服务器关闭的情况下停止循环。

    package main
    
    import (
        "fmt"
        "log"
        "net/http"
        "time"
    
        "github.com/rs/cors"
    )
    
    func main() {
        mux := http.NewServeMux()
    
    
        mux.HandleFunc("/sse", handleSse)
    
        c := cors.New(cors.Options{
            AllowedOrigins: []string{"*"},
            AllowedMethods: []string{http.MethodGet, http.MethodPost,
                http.MethodDelete, http.MethodPut},
            AllowCredentials: true,
        })
    
        handler := c.Handler(mux)
    
        log.Fatal(http.ListenAndServe(":6969", handler))
    }
    
    func handleSse(w http.ResponseWriter, r *http.Request) {
    
        w.Header().Set("Content-type", "text/event-stream")
        w.Header().Set("Cache-Control", "no-cache")
        w.Header().Set("Connection", "keep-alive")
        w.WriteHeader(http.StatusOK)
    
        f, ok := w.(http.Flusher)
        if !ok {
            http.Error(w, "SSE not supported , IE6 bruh",
                http.StatusBadRequest)
            return
        }
    
         // Send retry directive to client
        fmt.Fprintln(w, "retry: 10000")
        flusher.Flush()
    
        // Send events to the client every 2 seconds
        ticker := time.NewTicker(2 * time.Second)
        defer ticker.Stop()
    
        for {
            select {
            case <-r.Context().Done():
                fmt.Println("The client has disconnected or the server is shutting down"
                return
            case <-ticker.C:
                fmt.Fprintf(w, "data: %v\n\n", "Sorry")
                flusher.Flush()
            }
        }
    }
    
  • 当这个客户是唯一的客户时,它能正常工作吗?主题有多少个分区?你能提供一个最小的可重现示例吗?

  • 为了让同一组中的多个消费者使用同一个主题,您需要扩展主题上的分区。在您的例子中,扩展到 2 个。

    1 个分区意味着每次只有一个消费者读取该主题。

    注意 :您只能扩大分区。缩小到单个分区将需要删除并重新创建主题。

返回
作者最近主题: