当前位置: 首页 > article >正文

Go 如何优雅退出进程

优雅退出设计步骤

在 Go 项目中,设计优雅退出(Graceful Shutdown)时,通常需要确保在收到退出信号时,程序能够安全地清理资源并优雅地退出。以下是常见的优雅退出设计步骤:

步骤 1:创建 context.Contextcancel 函数

  • 使用 context.WithCancel() 创建一个取消上下文,用于传递取消信号。
  • cancel() 函数可以在收到退出信号时调用,从而通知所有正在运行的 goroutine 停止执行。

步骤 2:通过 context.WithCancel() 创建取消上下文

  • 为确保优雅退出,cancel() 函数需要在主线程的退出信号处理之前执行,保证所有协程能够及时响应取消信号。

步骤 3:处理所有协程的退出

  • 启动多个协程并确保它们能够响应 ctx.Done() 信号,及时停止执行并清理资源。
  • 使用 select 语句监听 ctx.Done(),以便协程能够在收到取消信号时退出。

步骤 4:触发 cancel() 并等待协程退出

  • 在收到退出信号(如系统信号 SIGINT, SIGTERM 等)时,优先调用 cancel(),以确保通知所有正在运行的协程退出。
  • 然后等待所有协程退出,通常使用 sync.WaitGroup 来等待所有协程完成退出。
package main

import (
	"context"
	"fmt"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"
)

func doWork(ctx context.Context, id int, wg *sync.WaitGroup) {
	defer wg.Done()
	for {
		select {
		case <-ctx.Done():
			// 当收到取消信号时,退出 goroutine
			fmt.Printf("goroutine %d: work cancelled\n", id)
			return
		default:
			// 模拟工作
			fmt.Printf("goroutine %d: working...\n", id)
			time.Sleep(1 * time.Second)
		}
	}
}

func main() {
	// 创建一个取消上下文
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	var wg sync.WaitGroup
	// 启动多个 goroutine
	for i := 0; i < 3; i++ {
		wg.Add(1)
		go doWork(ctx, i, &wg)
	}

	// 捕获终止信号
	signalChan := make(chan os.Signal, 1)
	// syscall.SIGINT: 终端执行 Ctrl + C
	// syscall.SIGTERM: 终端执行 kill $pid
	// syscall.SIGQUIT: 终端执行 Ctrl + \
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
	// 等待退出信号
	select {
	case <-signalChan:
		// 在退出信号到达时,先执行 cancel,发出取消信号
		fmt.Println("Received termination signal. Cancelling context...")
		cancel()

		// 等待所有 goroutine 完成退出
		wg.Wait()
		fmt.Println("Graceful shutdown completed.")
	}
}


http://www.kler.cn/a/465244.html

相关文章:

  • asp.net core mvc的 ViewBag 和 ViewData 和 Module
  • 《GICv3_Software_Overview_Official_Release_B》学习笔记
  • 消息中间件类型都有哪些
  • python3GUI--智慧交通监控与管理系统 By:PyQt5
  • 第2章:SQL基础
  • qml MouseArea详解
  • mysql之组内排序ROW_NUMBER()函数
  • Agent系列:AppAgent v2-屏幕智能Agent(详解版)
  • Ajax数据爬取
  • 定制级安全重保方案,确保重大活动期间的网络安全无忧
  • Tailwind CSS:现代 CSS 框架的优雅之选
  • redis的集群模式与ELK基础
  • STM32传感器系列:GPS定位模块
  • 活动预告 |【Part1】Microsoft Azure 在线技术公开课:使用 Azure DevOps 和 GitHub 加速开发
  • spring中使用@Validated,什么是JSR 303数据校验,spring boot中怎么使用数据校验
  • 【行空板K10】MQTT服务器SIoT V2
  • LeetCode - 初级算法 数组(旋转数组)
  • Vue.js组件开发-如何动态设置下拉框数值
  • 使用Python和OpenCV进行视觉图像分割
  • ASP.NET CORE 依赖注入的三种方式,分别是什么,使用场景
  • GitLab集成Runner详细版--及注意事项汇总【最佳实践】
  • vue + iview inputNumber最大最小值限制问题
  • windows remote desktop service 远程桌面RDS授权激活
  • 智能水文:ChatGPT等大语言模型如何提升水资源分析和模型优化的效率
  • 121.【C语言】数据结构之快速排序(未优化的Hoare排序存在的问题)以及时间复杂度的分析
  • mysql删除无用用户