本文介绍了去封装系统调用conn.Read()是非阻塞的并导致高CPU使用率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

奇怪的是,在我的情况下, Read()是非阻塞的,并且导致CPU占用率高。



My代码:

在函数 main 中:



<$ p $如果错误!=零(
log。),$ r $ = $。致命(错误)
}

为{
//等待连接。
conn,err:= l.Accept()
如果err!= nil {
log.Fatal(err)
}
//处理连接新goroutine。
//循环然后返回到接受状态,以便
//多个连接可以同时进行。
go reqHandler.TCPHandler(conn)

runtime.Gosched()
}

函数 TCPHandler

  func TCPHandler (conn net.Conn){
request:= make([] byte,4096)
for {
read_len,err:= conn.Read(request)

如果err!= nil {
如果err.Error()==使用关闭的网络连接{
LOG(Conn closed,可能发生错误)
break
}

neterr,ok:= err。(net.Error);
if ok&& neterr.Timeout(){
fmt.Println(neterr)
LOG(Client timeout!)
break
}
}

如果read_len == 0 {
LOG(Nothing read)
continue
} else {
//做某事
}
请求:= make([] byte,4096)
}
}

问题是, conn.Read()是非阻塞的,所以每次进入 LOG(Nothing read)然后继续,这会导致高CPU使用率。如何使 conn.Read()块调用?



我研究了 syscall 包,但是在 syscall.Read()
中得到了回扣因为我在OS X 10.8.3上发现了这个问题,相关源代码:



我没有理解什么 Syscall(SYS_READ,uintptr(fd),uintptr(_p0),uintptr(len(p)))表示。

解决方案

你没有正确处理TCP。当conn.Read()返回0字节时,表示对等体已经正常关闭了TCP连接。在这种情况下,您应该关闭TCP连接的结束。 (注意这对于Go来说并不特别,read()/ recv()在TCP连接上返回0通常意味着另一端已经关闭了连接)

Strangely, in my case Read() is non-blocking and caused high CPU usage.

My code:

In function main:

l, err := net.Listen("tcp", ":13798")


if err != nil {
    log.Fatal(err)
  }

  for {
    // Wait for a connection.
    conn, err := l.Accept()
    if err != nil {
      log.Fatal(err)
    }
    // Handle the connection in a new goroutine.
    // The loop then returns to accepting, so that
    // multiple connections may be served concurrently.
    go reqHandler.TCPHandler(conn)

    runtime.Gosched()
  }

Function TCPHandler:

func TCPHandler(conn net.Conn) {
request := make([]byte, 4096)
  for {
    read_len, err := conn.Read(request)

    if err != nil {
        if err.Error() == "use of closed network connection" {
        LOG("Conn closed, error might happened")
        break
      }

      neterr, ok := err.(net.Error);
      if ok && neterr.Timeout() {
        fmt.Println(neterr)
        LOG("Client timeout!")
        break
      }
    }

    if read_len == 0 {
     LOG("Nothing read")
      continue
    } else {
      // do something
    }
    request := make([]byte, 4096)
  }
}

The problem is, conn.Read() is non-blocking, so every time it goes to LOG("Nothing read") then continue, this is causing high CPU usage. How to make conn.Read() a block call?

I've researched into syscall package but got stucked at Syscall.Read()Since I found this issue on my OS X 10.8.3 here is the source code related:

http://golang.org/src/pkg/syscall/zsyscall_darwin_amd64.go?h=Read#L898

I have no idea what Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p))) means.

解决方案

You're not handling TCP correctly. When conn.Read() returns 0 bytes read, that means the peer has closed the TCP connection gracefully. You should probably close your end of the TCP connection in this case.

(Note that this is not special to Go, read()/recv() returning 0 on a TCP connection more or less universally means the other end has closed the connection)

这篇关于去封装系统调用conn.Read()是非阻塞的并导致高CPU使用率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 20:56