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

Gin优雅关闭 graceful-shutdown

文章目录

  • 优雅关闭示例 - Close 方法
    • 项目结构
    • 使用方法
    • 代码如下
    • 代码说明
    • 如果去掉代码中的数字1,会发生什么
  • 优雅关闭示例
    • 项目结构
    • 使用方法
      • 使用上下文通知
      • 不使用上下文通知
  • 代码 notify-without-context-server.go
    • 代码说明
  • 代码 notify-with-context-server.go
    • 代码说明

优雅关闭示例 - Close 方法

此示例演示了如何使用 server.Close() 方法在 Gin 服务器中实现优雅关闭。

项目结构

  • server.go:处理优雅关闭的主服务器实现文件。

使用方法

  1. 安装所需依赖:

    go get -u github.com/gin-gonic/gin
    
  2. 运行服务器:

    go run server.go
    
  3. 访问服务器地址:http://localhost:8080/

  4. 要触发优雅关闭,发送中断信号(例如在终端中按 Ctrl+C)。服务器将在关闭前完成所有正在处理的请求。

代码如下

//go:build go1.8
// +build go1.8package mainimport ("log""net/http""os""os/signal""time""github.com/gin-gonic/gin"
)func main() {router := gin.Default()router.GET("/", func(c *gin.Context) {time.Sleep(5 * time.Second)c.String(http.StatusOK, "Welcome Gin Server")})server := &http.Server{Addr:    ":8080",Handler: router,}quit := make(chan os.Signal, 1)signal.Notify(quit, os.Interrupt)go func() {<-quitlog.Println("receive interrupt signal")if err := server.Close(); err != nil {log.Fatal("Server Close:", err)}}()if err := server.ListenAndServe(); err != nil {if err == http.ErrServerClosed {log.Println("Server closed under request")} else {log.Fatal("Server closed unexpect")}}log.Println("Server exiting")
}

代码说明

  • 服务器初始化时包含一个简单路由,该路由模拟了 5 秒的延迟。
  • 创建了一个通道来监听中断信号。
  • 当接收到中断信号时,使用 server.Close() 方法优雅地关闭服务器。

如果去掉代码中的数字1,会发生什么

在这里插入图片描述
报警告
misuse of unbuffered os.Signal channel as argument to signal.Notify sigchanyzer(default)

修复如下

  1. 简要解释报错原因:
    未缓冲的 os.Signal channel 用于 signal.Notify,可能导致信号丢失。

  2. 修复建议:
    quit channel 改为带缓冲的 channel,例如 make(chan os.Signal, 1),以确保信号能被正确接收。

  3. 修复后的代码(仅展示修改部分):

// 原代码:
// quit := make(chan os.Signal)
// 修改为:
quit := make(chan os.Signal, 1)signal.Notify(quit, os.Interrupt)
  1. 说明:
    使用带缓冲的 channel 可防止在 signal.Notify 接收前信号到达而被丢弃,避免潜在的阻塞或行为异常问题。这是 Go 中处理系统信号的标准做法。

优雅关闭示例

本目录包含使用上下文(Context)和不使用上下文两种方式实现Gin服务器优雅关闭的示例。

项目结构

  • notify-with-context/: 使用上下文实现优雅关闭的示例
  • notify-without-context/: 不使用上下文实现优雅关闭的示例

使用方法

使用上下文通知

  1. 安装所需依赖:

    go get -u github.com/gin-gonic/gin
    
  2. 运行服务器:

    go run notify-with-context/server.go
    
  3. 访问服务器地址:http://localhost:8080/

  4. 要触发优雅关闭,发送中断信号(如在终端中按Ctrl+C)。服务器将在关闭前完成所有正在处理的请求。

不使用上下文通知

  1. 安装所需依赖:

    go get -u github.com/gin-gonic/gin
    
  2. 运行服务器:

    go run notify-without-context/server.go
    
  3. 访问服务器地址:http://localhost:8080/

  4. 要触发优雅关闭,发送中断信号(如在终端中按Ctrl+C)。服务器将在关闭前完成所有正在处理的请求。

代码 notify-without-context-server.go

//go:build go1.8
// +build go1.8package mainimport ("context""log""net/http""os""os/signal""syscall""time""github.com/gin-gonic/gin"
)func main() {router := gin.Default()router.GET("/", func(c *gin.Context) {time.Sleep(5 * time.Second)c.String(http.StatusOK, "Welcome Gin Server")})srv := &http.Server{Addr:    ":8080",Handler: router,}// Initializing the server in a goroutine so that// it won't block the graceful shutdown handling belowgo func() {if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {log.Fatalf("listen: %s\n", err)}}()// Wait for interrupt signal to gracefully shutdown the server with// a timeout of 5 seconds.quit := make(chan os.Signal, 1)// kill (no param) default send syscall.SIGTERM// kill -2 is syscall.SIGINT// kill -9 is syscall.SIGKILL but can't be catch, so don't need add itsignal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)// 从quit中接收值,忽略结果 <-quit log.Println("Shutting down server...")// The context is used to inform the server it has 5 seconds to finish// the request it is currently handlingctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)defer cancel()if err := srv.Shutdown(ctx); err != nil {log.Fatal("Server forced to shutdown: ", err)}log.Println("Server exiting")
}

代码说明

不使用上下文示例

  • 服务器初始化时包含一个简单路由,该路由模拟了5秒的延迟
  • 创建了一个通道来监听中断信号
  • 当接收到中断信号时,使用带超时的server.Shutdown()方法优雅地关闭服务器

代码 notify-with-context-server.go

//go:build go1.16package mainimport ("context""log""net/http""os/signal""syscall""time""github.com/gin-gonic/gin"
)func main() {// Create context that listens for the interrupt signal from the OS.ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)defer stop()router := gin.Default()router.GET("/", func(c *gin.Context) {time.Sleep(10 * time.Second)c.String(http.StatusOK, "Welcome Gin Server")})srv := &http.Server{Addr:    ":8080",Handler: router,}// Initializing the server in a goroutine so that// it won't block the graceful shutdown handling belowgo func() {if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {log.Fatalf("listen: %s\n", err)}}()// Listen for the interrupt signal.<-ctx.Done()// Restore default behavior on the interrupt signal and notify user of shutdown.stop()log.Println("shutting down gracefully, press Ctrl+C again to force")// The context is used to inform the server it has 5 seconds to finish// the request it is currently handlingctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)defer cancel()if err := srv.Shutdown(ctx); err != nil {log.Fatal("Server forced to shutdown: ", err)}log.Println("Server exiting")
}

代码说明

使用上下文示例

  • 服务器初始化时包含一个简单路由,该路由模拟了10秒的延迟
  • 创建了一个监听中断信号的上下文
  • 当接收到中断信号时,使用上下文优雅地关闭服务器

相关文章:

Gin优雅关闭 graceful-shutdown

文章目录 优雅关闭示例 - Close 方法项目结构使用方法代码如下代码说明如果去掉代码中的数字1&#xff0c;会发生什么 优雅关闭示例项目结构使用方法使用上下文通知不使用上下文通知 代码 notify-without-context-server.go代码说明 代码 notify-with-context-server.go代码说明…...

Android 查看 Logcat (可纯手机方式 无需电脑)

安装 Logcat Reader Github Google Play 如果有电脑 使用其ADB方式可执行如下命令 后续无需安装Termux # 使用 ADB 授予 android.permission.READ_LOGS 权限给 Logcat Reader adb shell "pm grant com.dp.logcatapp android.permission.READ_LOGS && am force-…...

Java 中常见的数据结构及其常用 API

本文总结了 Java 中常见的数据结构及其常用 API&#xff0c;帮助开发者在写算法时能够快速选择合适的数据结构和操作。通过使用合适的 API&#xff0c;可以有效减少计算复杂度&#xff0c;并提高代码的执行效率。 1. 数组 数组是 Java 中最常用的数据结构之一&#xff0c;Jav…...

五子棋html

<!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8" /> <meta name"viewport" content"widthdevice-width, initial-scale1" /> <title>五子棋游戏</title> <style>bo…...

在Laravel 12中实现基于parent_id的树状数组

在Laravel中实现基于parent_id的树状数组&#xff0c;可以通过预加载所有节点并在内存中递归构建树结构来完成。以下是具体步骤和代码示例&#xff1a; 1. 创建模型及数据库迁移 迁移文件&#xff1a; // 创建节点表 Schema::create(nodes, function (Blueprint $table) {$t…...

JavaWeb:后端web基础(TomcatServletHTTP)

一、今日内容 二、Tomcat 介绍与使用 介绍 基本使用 小结 配置 配置 查找进程 三、Servlet 什么是Servlet 快速入门 需求 步骤 1.新建工程-模块&#xff08;Maven&#xff09; 2.修改打包方式-war 3.编写代码 /*** 可以选择继承HttpServlet*/ WebServlet("/hello&q…...

C++负载均衡远程调用学习之负载均衡算法与实现

目录 01 lars 系统架构回顾 02 lars-lbAgentV0.4-route_lb处理report业务流程 03 lars-lbAgentV0.4-负责均衡判断参数配置 04 lars-lbAgentV0.4-负载均衡idle节点的失败率判断 05 lars-lbAgentV0.4-负载均衡overload节点的成功率判断 06 lars-lbAgentV0.4-负载均衡上报提交…...

缓存(1):三级缓存

三级缓存是指什么 我们常说的三级缓存如下&#xff1a; CPU三级缓存Spring三级缓存应用架构&#xff08;JVM、分布式缓存、db&#xff09;三级缓存 CPU 基本概念 CPU 的访问速度每 18 个月就会翻 倍&#xff0c;相当于每年增⻓ 60% 左右&#xff0c;内存的速度当然也会不断…...

Cursor —— AI编辑器 使用详解

Cursor - The AI Code Editor 一、Cursor 是什么&#xff1f; Cursor 是一款优秀的AI代码编辑器&#xff0c;它内置了 Deepseek-R1、GPT-4、Claude等 AI 模型。 简单说&#xff0c;就是&#xff1a;Cursor VS Code 编辑器 AI 大模型 Cursor 功能特性&#xff08;代码补全、…...

Pytorch-CUDA版本环境配置

Pytorch-CUDA版本环境配置 电脑如果是Windows平台下的Nvidia GPU的用户&#xff0c;需配置Pytorch的CUDA版本&#xff0c;分为三步&#xff1a; 1. 安装或更新NVIDA显卡驱动 官方驱动下载地址&#xff1a; https://www.nvidia.cn/Download/index.aspx?langcn 2. 安装CUDA Too…...

一个完整的神经网络训练流程详解(附 PyTorch 示例)

&#x1f9e0; 一个完整的神经网络训练流程详解&#xff08;附 PyTorch 示例&#xff09; &#x1f4cc; 第一部分&#xff1a;神经网络训练流程概览&#xff08;总&#xff09; 在深度学习中&#xff0c;构建和训练一个神经网络模型并不是简单的“输入数据、得到结果”这么简…...

OpenCV 图形API(77)图像与通道拼接函数-----对图像进行几何变换函数remap()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 对图像应用一个通用的几何变换。 函数 remap 使用指定的映射对源图像进行变换&#xff1a; dst ( x , y ) src ( m a p x ( x , y ) , m a p y…...

windows通过wsl安装ubuntu20.04

1 *.bat文件安装hyper-v pushd "%~dp0" dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt for /f %%i in (findstr /i . hyper-v.txt 2^>nul) do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i"…...

Spring AI 入门(持续更新)

介绍 Spring AI 是 Spring 项目中一个面向 AI 应用的模块&#xff0c;旨在通过集成开源框架、提供标准化的工具和便捷的开发体验&#xff0c;加速 AI 应用程序的构建和部署。 依赖 <!-- 基于 WebFlux 的响应式 SSE 传输 --> <dependency><groupId>org.spr…...

QUIC协议优化:HTTP_3环境下的超高速异步抓取方案

摘要 随着 QUIC 和 HTTP/3 的普及&#xff0c;基于 UDP 的连接复用与内置加密带来了远超 HTTP/2 的性能提升&#xff0c;可显著降低连接握手与拥塞恢复的开销。本文以爬取知乎热榜数据为目标&#xff0c;提出一种基于 HTTPX aioquic 的异步抓取方案&#xff0c;并结合代理 IP设…...

uni-app实现完成任务解锁拼图功能

界面如下 代码如下 <template><view class"puzzle-container"><view class"puzzle-title">任务进度 {{completedCount}}/{{totalPieces}}</view><view class"puzzle-grid"><viewv-for"(piece, index) in…...

Vue3 中当组件嵌套层级较深导致 ref 无法直接获取子组件实例时,可以通过 provide/inject + 回调函数的方式实现子组件方法传递到父组件

需求&#xff1a;vue3中使用defineExposeref调用子组件方法报错不是一个function 思路&#xff1a;由于组件嵌套层级太深导致ref失效&#xff0c;通过provide/inject 回调函数来实现多层穿透 1. 父组件提供「方法注册函数」 父组件通过 provide 提供一个用于接收子组件方法…...

关于 js:3. 闭包、作用域、内存模型

一、闭包的本质&#xff1a;函数 其词法作用域环境 闭包&#xff08;Closure&#xff09;的本质可以概括为&#xff1a; 闭包是一个函数&#xff0c;以及它定义时捕获的词法作用域中的变量集合。 这意味着&#xff1a;即使外部函数已经返回或作用域结束&#xff0c;只要有内…...

数据链路层(MAC 地址)

目录 一、前言&#xff1a; 二、以太网&#xff1a; 三、MAC 地址的作用&#xff1a; 四、ARP协议&#xff1a; 一、前言&#xff1a; 数据链路层主要负责相邻两个节点之间的数据传输&#xff0c;其中&#xff0c;最常见数据链路层的协议有 以太网&#xff08;通过光纤 / 网…...

基于DQN的自动驾驶小车绕圈任务

1.任务介绍 任务来源: DQN: Deep Q Learning &#xff5c;自动驾驶入门&#xff08;&#xff1f;&#xff09; &#xff5c;算法与实现 任务原始代码: self-driving car 最终效果&#xff1a; 以下所有内容&#xff0c;都是对上面DQN代码的改进&#…...

terraform resource创建了5台阿里云ecs,如要使用terraform删除其中一台主机,如何删除?

在 Terraform 中删除阿里云 5 台 ECS 实例中的某一台&#xff0c;具体操作取决于你创建资源时使用的 多实例管理方式&#xff08;count 或 for_each&#xff09;。以下是详细解决方案&#xff1a; 方法一&#xff1a;使用 for_each&#xff08;推荐&#xff09; 如果创建时使…...

【Linux】Linux工具(1)

3.Linux工具&#xff08;1&#xff09; 文章目录 3.Linux工具&#xff08;1&#xff09;Linux 软件包管理器 yum什么是软件包关于 rzsz查看软件包——yum list命令如何安装软件如何卸载软件补充——yum如何找到要安装软件的下载地址 Linux开发工具Linux编辑器-vim使用1.vim的基…...

探索大语言模型(LLM):词袋法(Bag of Words)原理与实现

文章目录 引言一、词袋法原理1.1 核心思想1.2 实现步骤 二、数学公式2.1 词频表示2.2 TF-IDF加权&#xff08;可选&#xff09; 三、示例表格3.1 构建词汇表3.2 文本向量化&#xff08;词频&#xff09; 四、Python代码实现4.1 基础实现&#xff08;手动计算&#xff09;4.2 输…...

vue引入物理引擎matter.js

vue引入物理引擎matter.js 在 Vue 项目中集成 Matter.js 物理引擎的步骤如下: 1. 安装 Matter.js npm install matter-js # 或 yarn add matter-js2. 创建 Vue 组件 <template><div ref="physicsContainer" class="physics-container"><…...

基于 Spring Boot 瑞吉外卖系统开发(十一)

基于 Spring Boot 瑞吉外卖系统开发&#xff08;十一&#xff09; 菜品启售和停售 “批量启售”、“批量停售”、操作列的售卖状态绑定单击事件&#xff0c;触发单击事件时&#xff0c;最终携带需要修改售卖状态的菜品id以post请求方式向“/dish/status/{params.status}”发送…...

支持鸿蒙next的uts插件

*本文共四个功能函数&#xff0c;相当于四个插件。作者为了偷懒写成了一个插件&#xff0c;调对应的函数即可。 1、chooseImageHarmony函数&#xff1a;拉起相册选择图片并转为Base64 2、takePhotoAndConvertToBase64函数&#xff1a;拉起相机拍照并转为Base64 3、openBrows…...

深入理解负载均衡:传输层与应用层的原理与实战

目录 前言1. 传输层&#xff08;Layer 4&#xff09;负载均衡1.1 工作层级与核心机制1.2 实现方式详解1.3 优缺点分析1.4 典型实现工具 2. 应用层&#xff08;Layer 7&#xff09;负载均衡2.1 工作层级与核心机制2.2 实现方式解析2.3 优缺点分析2.4 常用实现工具 3. Layer 4 与…...

WPF之Slider控件详解

文章目录 1. 概述2. 基本属性2.1 值范围属性2.2 滑动步长属性2.3 刻度显示属性2.4 方向属性2.5 选择范围属性 3. 事件处理3.1 值变化事件3.2 滑块拖动事件 4. 样式和模板自定义4.1 基本样式设置4.2 控件模板自定义 5. 数据绑定5.1 绑定到ViewModel5.2 同步多个控件 6. 实际应用…...

极狐GitLab 如何将项目共享给群组?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 共享项目和群组 (BASIC ALL) 在极狐GitLab 16.10 中&#xff0c;更改为在成员页面的成员选项卡上显示被邀请群组成员&#xf…...

企业微信自建消息推送应用

企业微信自建应用来推送消息 前言 最近有个给特定部门推送消息的需求&#xff0c;所以配置一个应用专门用来推送消息。实现过程大致为&#xff1a;服务器生成每天的报告&#xff0c;通过调用API来发送消息。以前一直都是发邮件&#xff0c;整个邮箱里全是报告文件&#xff0c…...