Heim > Backend-Entwicklung > Golang > So implementieren Sie die Hot-Switch-Funktion des Go-Programms cooler

So implementieren Sie die Hot-Switch-Funktion des Go-Programms cooler

Freigeben: 2023-07-21 12:00:03
nach vorne
1199 Leute haben es durchsucht
Während der Entwicklung benötigen wir häufig Thermoschalter, d. h. bestimmte Funktionen können zu geeigneten Zeiten ein- oder ausgeschaltet werden, während das Programm läuft. Beispielsweise ist die in der Leistungsanalyse verwendete pprof-Probenahme ein typischer Thermoschalter. In diesem Artikel wird erläutert, wie dieser Thermoschalter kühler wird.

Bevor wir die neue Lösung vorstellen, schauen wir uns an, wie pprof in Go-Programmen durchgeführt wird.

Schnittstellenaufruf

Leistungstests des Programms können sich auf seine Servicefunktionen auswirken. Daher wird die Online-Probenahme im Allgemeinen innerhalb eines festgelegten kleinen Zeitbereichs durchgeführt und erfordert eine effektive Schaltersteuerung.

Um dies zu erreichen, führen wir im Allgemeinen das Paket net/http/pprof (seine Init-Funktion ist an die Routing-Funktion gebunden) in den Code ein. Die Sampling-Funktion wird aktiviert, wenn von außen auf den HTTP-Dienst des angegebenen Ports zugegriffen wird. Nach Ablauf der Sampling-Zeit wird die Erfassung deaktiviert.

Der Implementierungscode lautet wie folgt

package main

import (
 "net/http"
 _ "net/http/pprof"
)

func main() {
 go func() {
  _ = http.ListenAndServe(":8080", nil)
 }()
 ...
}
Nach dem Login kopieren

Mit diesem Ansatz gibt es natürlich kein Problem. Wir können es lernen und andere Switch-Funktionen in HTTP-Dienste umwandeln. Aber gibt es einen anderen cooleren Weg?

信号通知

信号处理与 Go 程序的优雅退出一文中,我们谈论过信号机制,它用以向应用程序发送某种事件通知。

我们可以将基于接口触发的方式改为信号通知。

首先,构造采样功能函数(对应于 net/http/pprof 包下 init 函数中绑定的路由功能函数)。

func RegisterSignalForProfiling(sig os.Signal) {
 ch := make(chan os.Signal)
 started := false
 signal.Notify(ch, sig)

 go func() {
  var memoryProfile, cpuProfile, traceProfile *os.File
  for range ch {
   if started {
    pprof.StopCPUProfile()
    trace.Stop()
    pprof.WriteHeapProfile(memoryProfile)
    memoryProfile.Close()
    cpuProfile.Close()
    traceProfile.Close()
    started = false
   } else {
    cpuProfile, _ = os.Create("cpu.pprof")
    memoryProfile, _ = os.Create("memory.pprof")
    traceProfile, _ = os.Create("runtime.trace")
    pprof.StartCPUProfile(cpuProfile)
    trace.Start(traceProfile)
    started = true
   }
  }
 }()
}
Nach dem Login kopieren

在上述函数中,我们定义了接收信号通道<span style="font-size: 15px;">ch</span>,通过<span style="font-size: 15px;">signal.Notify(ch, sig)</span>将指定的通知信号<span style="font-size: 15px;">sig</span><span style="font-size: 15px;">ch</span>进行绑定。<span style="font-size: 15px;">for range ch</span> 将阻塞等待外部信号<span style="font-size: 15px;">sig</span>,随着<span style="font-size: 15px;">sig</span>信号的到来,交替进入开启或关闭采样的逻辑。

<span style="font-size: 15px;">main</span>函数中,就可以这样替代<span style="font-size: 15px;">http.ListenAndServe(":8080", nil)</span>了。

package main

import (
  "syscall"
  ...
)

func main() {
  RegisterSignalForProfiling(syscall.Signal(31))
 ...
}
Nach dem Login kopieren

在 linux 系统,可以通过<span style="font-size: 15px;">kill -signal_number pid</span>命令向程序发送指定信号。

如上代码所示,我们硬编码指定的采样开关信号值是 31。因此,当程序运行起来后,我们在控制台输入<span style="font-size: 15px;">kill -31 pid</span> 命令,即可开启采样,再次输入<span style="font-size: 15px;">kill -31 pid</span>命令,就关闭了采样。

依葫芦画瓢,我们再来一个打印 goroutine 堆栈信息的热开关函数,是不是很酷?

func RegisterSignalForPrintStack(sig os.Signal) {
 ch := make(chan os.Signal)
 signal.Notify(ch, sig)

 go func() {
  for range ch {
   buffer := make([]byte, 1024*1024*4)
   runtime.Stack(buffer, true)
   fmt.Println(string(buffer))
  }
 }()
}
Nach dem Login kopieren

总结

热开关是一个很简单常用的功能,无非是选择何种触发与等待方式。基于接口的调用更适合于远程控制,基于信号则便于本地控制。

Das obige ist der detaillierte Inhalt vonSo implementieren Sie die Hot-Switch-Funktion des Go-Programms cooler. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:Go语言进阶学习
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage