Hook系统调用

可以用来拦截网络流量

  1. package hook
  2. import (
  3. "net"
  4. "runtime"
  5. "syscall"
  6. )
  7. // GetCurrentGoRoutineID GetCurrentGoRoutineID
  8. func GetCurrentGoRoutineID() int64 {
  9. return runtime.GetCurrentGoRoutineId()
  10. }
  11. // SetDelegatedFromGoRoutineID SetDelegatedFromGoRoutineID
  12. func SetDelegatedFromGoRoutineID(gID int64) {
  13. runtime.SetDelegatedFromGoRoutineId(gID)
  14. }
  15. // RegisterOnConnect RegisterOnConnect
  16. func RegisterOnConnect(callback func(fd int, sa syscall.Sockaddr)) {
  17. syscall.OnConnect = callback
  18. }
  19. // RegisterOnAccept RegisterOnAccept
  20. func RegisterOnAccept(callback func(serverSocketFD int, clientSocketFD int, sa syscall.Sockaddr)) {
  21. syscall.OnAccept = callback
  22. }
  23. // RegisterOnRecv RegisterOnRecv
  24. func RegisterOnRecv(callback func(fd int, net string, raddr net.Addr, span []byte)) {
  25. net.OnRead = callback
  26. }
  27. // RegisterOnSend RegisterOnSend
  28. func RegisterOnSend(callback func(fd int, net string, raddr net.Addr, span []byte)) {
  29. net.OnWrite = callback
  30. }
  31. // RegisterOnClose RegisterOnClose
  32. func RegisterOnClose(callback func(fd int)) {
  33. net.OnClose = callback
  34. }
  35. // RegisterOnGoRoutineExit RegisterOnGoRoutineExit
  36. func RegisterOnGoRoutineExit(callback func(goid int64)) {
  37. runtime.OnGoRoutineExit = callback
  38. }

go:linkname

可以实现引导编译器将当前(私有)方法或者变量在编译时链接到指定的位置的方法或者变量,第一个参数表示当前方法或变量,第二个参数表示目标方法或变量,因为这关指令会破坏系统和包的模块化,因此在使用时必须导入unsafe

Prof

如果你的go程序不是web服务器,而是一个服务进程,那么你也可以选择使用net/http/pprof包,同样引入包net/http/pprof,然后在开启另外一个goroutine来开启端口监听。

  1. go func() {
  2. log.Println(http.ListenAndServe("localhost:6060", nil))
  3. }()

调用go tool pprof http://localhost:3999/debug/pprof/profile来开始采集数据,
之后输入png就可以生成一个调用图
image.png
pprof现在支持加label可以观察时间都耗费在哪里