Go-gin-example 第四部分 重启服务

文章目录

  • 知识点
  • 本节目标
    • 何谓优雅
  • ctrl+c
    • 信号
  • 修改流程
  • 实现优雅重启
    • endless
      • 安装
    • 编写
    • 验证
      • 编译
      • 执行
      • 唤醒
      • 问题

续接 上一节

知识点

  • 信号量的了解
  • 应用热更新

本节目标

在前文中,我们在配置玩之后直接使用 ctrl+c 来进行进程的结束,我们将了解 ctrl+c 的过程中到底进行了什么
简单讲述 ctrl+c 背后的信号 以及如何在gin优雅的重启服务,也就是对HTTP服务进行热更新

何谓优雅

  • 不关闭现有连接(正在运行中的程序)
  • 新的进程启动并替代旧进程
  • 新的进程接管新的连接
  • 连接要随时相应用户的请求,当用户仍在请求旧进程时要保持连接,新用户应请求新进程,不可以出现拒绝请求的情况

ctrl+c

内核在某些情况下发送信号,比如在进程往一个已经关闭的管道写数据时会产生SIGPIPE信号
我们在执行ctrl+c关闭gin服务端时,会强制结束进程,导致正在访问的用户等出现问题

信号

信号Unix类 Unix 以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式

它是一种异步的通知机制,用来提醒进程一个事件(硬件异常、程序执行异常、外部发出信号)已经发生。当一个信号发送给一个进程,操作系统中断了进程正常的控制流程。此时,任何非原子操作都将被中断。如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数

修改流程

  1. 替换可执行文件或修改配置文件
  2. 发送信号量
  3. 拒绝新连接请求旧进程,但要保证已有连接进程
  4. 去启动新的子进程
  5. 新的子进程开始accept
  6. 系统将新的请求转交新的子进程
  7. 旧进程处理玩所有旧连接后正常结束

实现优雅重启

我们借助 fvbock/endless 来实现 Golang HTTP/HTTPS 服务重新启动的零停机

endless

借助 fvbock/endless 来实现 Golang HTTP/HTTPS 服务重新启动的零停机

endless server监听以下几种信号量:

  • syscall.SIGHUP:触发 fork 子进程和重新启动
  • syscall.SIGUSR1/syscall.SIGTSTP:被监听,但不会触发任何动作
  • syscall.SIGUSR2:触发 hammerTime
  • syscall.SIGINT/syscall.SIGTERM:触发服务器关闭(会完成正在运行的请求)

安装

go get -u github.com/fvbock/endless

编写

打开 gin-blogmain.go文件,修改文件:

...
func main() {/*	之前的版本//将原来创建的默认router和建立对应的handler绑定router := routers.InitRouter()//创建一个http服务器,将前面的router绑定为这里的处理器s := &http.Server{Addr:           fmt.Sprintf(":%d", setting.HTTPPort),Handler:        router,ReadTimeout:    setting.ReadTimeout,WriteTimeout:   setting.WriteTimeout,MaxHeaderBytes: 1 << 20,}//启动服务器s.ListenAndServe()*///当前版本,建议对比源代码进行理解//进行配置的导入,在setting包中进行设置endless.DefaultReadTimeOut = setting.ReadTimeoutendless.DefaultWriteTimeOut = setting.WriteTimeoutendless.DefaultMaxHeaderBytes = 1 << 20endPoint := fmt.Sprintf(":%d", setting.HTTPPort)//newsever返回一个初始化的endlessServer对象server := endless.NewServer(endPoint, routers.InitRouter())//输出当前进程的PIDserver.BeforeBegin = func(add string) {log.Printf("Actual pid is %d", syscall.Getpid())}//启动服务err := server.ListenAndServe()if err != nil {log.Printf("Server err: %v", err)}}

验证

编译

$ go build main.go

执行

$ ./main
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.- using env:   export GIN_MODE=release- using code:  gin.SetMode(gin.ReleaseMode)[GIN-debug] GET    /auth                     --> github.com/kingsill/gin-example/routers/api.GetAuth (3 handlers)
[GIN-debug] GET    /api/v1/tags              --> github.com/kingsill/gin-example/routers/api/v1.GetTags (4 handlers)
[GIN-debug] POST   /api/v1/tags              --> github.com/kingsill/gin-example/routers/api/v1.AddTag (4 handlers)
[GIN-debug] PUT    /api/v1/tags/:id          --> github.com/kingsill/gin-example/routers/api/v1.EditTag (4 handlers)
[GIN-debug] DELETE /api/v1/tags/:id          --> github.com/kingsill/gin-example/routers/api/v1.DeleteTag (4 handlers)
[GIN-debug] GET    /api/v1/articles          --> github.com/kingsill/gin-example/routers/api/v1.GetArticles (4 handlers)
[GIN-debug] GET    /api/v1/articles/:id      --> github.com/kingsill/gin-example/routers/api/v1.GetArticle (4 handlers)
[GIN-debug] POST   /api/v1/articles          --> github.com/kingsill/gin-example/routers/api/v1.AddArticle (4 handlers)
[GIN-debug] PUT    /api/v1/articles/:id      --> github.com/kingsill/gin-example/routers/api/v1.EditArticle (4 handlers)
[GIN-debug] DELETE /api/v1/articles/:id      --> github.com/kingsill/gin-example/routers/api/v1.DeleteArticle (4 handlers)
2024/03/04 20:08:31 Actual pid is 593

可以看到我们当前的进程pid593,在另一个终端执行kill -1 48601

2024/03/04 20:09:21 593 Received SIGHUP. forking.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.- using env:   export GIN_MODE=release- using code:  gin.SetMode(gin.ReleaseMode)[GIN-debug] GET    /auth                     --> github.com/kingsill/gin-example/routers/api.GetAuth (3 handlers)
[GIN-debug] GET    /api/v1/tags              --> github.com/kingsill/gin-example/routers/api/v1.GetTags (4 handlers)
[GIN-debug] POST   /api/v1/tags              --> github.com/kingsill/gin-example/routers/api/v1.AddTag (4 handlers)
[GIN-debug] PUT    /api/v1/tags/:id          --> github.com/kingsill/gin-example/routers/api/v1.EditTag (4 handlers)
[GIN-debug] DELETE /api/v1/tags/:id          --> github.com/kingsill/gin-example/routers/api/v1.DeleteTag (4 handlers)
[GIN-debug] GET    /api/v1/articles          --> github.com/kingsill/gin-example/routers/api/v1.GetArticles (4 handlers)
[GIN-debug] GET    /api/v1/articles/:id      --> github.com/kingsill/gin-example/routers/api/v1.GetArticle (4 handlers)
[GIN-debug] POST   /api/v1/articles          --> github.com/kingsill/gin-example/routers/api/v1.AddArticle (4 handlers)
[GIN-debug] PUT    /api/v1/articles/:id      --> github.com/kingsill/gin-example/routers/api/v1.EditArticle (4 handlers)
[GIN-debug] DELETE /api/v1/articles/:id      --> github.com/kingsill/gin-example/routers/api/v1.DeleteArticle (4 handlers)
2024/03/04 20:09:21 Actual pid is 699
2024/03/04 20:09:21 593 Received SIGTERM.
2024/03/04 20:09:21 593 Waiting for connections to finish...
2024/03/04 20:09:21 593 Serve() returning...
2024/03/04 20:09:21 Server err: accept tcp [::]:8000: use of closed network connection

可以看到该命令已经挂起,并且fork了新的进程pid为699

唤醒

这时候在 postman 上再次访问我们的接口

╭─  │  ~/gin-example │   main ?1 ········································· ✔ │ 50s  │ 08:09:21 PM 
╰─
(/home/wang2/gin-example/models/article.go:45)
[2024-03-04 20:09:45]  [0.67ms]  SELECT * FROM `blog_article`   LIMIT 10 OFFSET 0
[0 rows affected or returned ]

postman继续访问时,当前终端从命令行重新进入程序的执行过程中
这就完成了一次正向的流转了

你想想,每次更新发布、或者修改配置文件等,只需要给该进程发送SIGTERM 信号,而不需要强制结束应用,是多么便捷又安全的事!

问题

endless 热更新是采取创建子进程后,将原进程退出的方式,这点不符合守护进程的要求

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/720228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS | 状态管理(九) | Environment (设备环境查询)

系列文章目录 1.HarmonyOS | 状态管理(一) | State装饰器 2.HarmonyOS | 状态管理(二) | Prop装饰器 3.HarmonyOS | 状态管理(三) | Link装饰器 4.HarmonyOS | 状态管理(四) | Provide和Consume装饰器 5.HarmonyOS | 状态管理(五) | Observed装饰器和ObjectLink装饰器 6.Harmo…

为啥要用C艹不用C?

在很多时候&#xff0c;有人会有这样的疑问 ——为什么要用C&#xff1f;C相对于C优势是什么&#xff1f; 最近两年一直在做Linux应用&#xff0c;能明显的感受到C带来到帮助以及快感 之前&#xff0c;我在文章里面提到环形队列 C语言&#xff0c;环形队列 环形队列到底是怎么回…

NLP_文本数据分析_3(代码示例)

目标 了解文本数据分析的作用.掌握常用的几种文本数据分析方法. 1 文件数据分析介绍 文本数据分析的作用: 文本数据分析能够有效帮助我们理解数据语料, 快速检查出语料可能存在的问题, 并指导之后模型训练过程中一些超参数的选择. 常用的几种文本数据分析方法: 标签数量分布句…

阿里云的ssh的22端口,修改为2422端口,作为默认的ssh端口

要将阿里云&#xff08;或任何Linux服务器&#xff09;的SSH端口从默认的22端口更改为2422端口&#xff0c;你可以按照以下步骤操作&#xff1a; 编辑SSH配置文件&#xff1a; 打开SSH服务的配置文件/etc/ssh/sshd_config。你可以使用nano、vi或任何文本编辑器来编辑这个文件。…

Vue3_2024_4天【computer、watch、method在Vue2~3中的说明】未完待补

第一&#xff1a;从概念上介绍~~vue中计算属性、方法、监听器&#xff08;以Vue2描述&#xff09; 1.计算属性 (Computed Properties): 1.概念&#xff1a; 计算属性是基于响应式依赖进行缓存的属性&#xff0c;只有在相关依赖发生改变时才会重新求值。它们类似于具有缓存的函…

场景问题: VisualVM工具Profiler JDBC不是真实执行的SQL

1. 问题 诡异的问题表象&#xff1a; 前端反馈分页接口的Total字段一直为0 使用Visualvm中的 Profiler 注入到应用后&#xff0c;查看JDBC监控得到了分页接口执行的SQL&#xff0c;复制出来执行是55. 此时还没有注意到 IN 的范围中有一个特别的值 NULL &#x1f928; 2. 排查…

视觉Transformers中的位置嵌入 - 研究与应用指南

视觉 Transformer 中位置嵌入背后的数学和代码简介。 自从 2017 年推出《Attention is All You Need》以来&#xff0c;Transformer 已成为自然语言处理 (NLP) 领域最先进的技术。 2021 年&#xff0c;An Image is Worth 16x16 Words 成功地将 Transformer 应用于计算机视觉任务…

Windows C++:控制新进程的创建方式

目录 介绍 标志位介绍 代码示例 这些宏定义&#xff08;dwCreationFlag值&#xff09;是用于Windows操作系统中CreateProcess函数的标志&#xff0c;它们控制新进程的创建方式。下面是这些标志的中文介绍&#xff1a; 介绍 Winbase.h中的部分代码&#xff1a; // // Proc…

idea中引入新JDK环境

在不同的项目中往往会需要不同的运行环境&#xff0c;那么如何下载一个新的环境并运用到idea中呢&#xff1f; 下面给出的就是oracle官网&#xff0c;以JDK17为例教大家如何下载 Java Archive Downloads - GraalVM for JDK 17https://www.oracle.com/java/technologies/javase…

Python数据可视化库之bashplotlib使用详解

概要 在数据可视化领域,Python拥有许多优秀的库,如Matplotlib、Seaborn等,它们可以创建漂亮而复杂的图形。但是,有时候我们可能需要在终端中绘制简单的图形,这时候Bashplotlib就派上了用场。Bashplotlib是一个Python库,可以在终端中绘制基本的图形,如条形图、散点图等。…

YOLOV9训练集制作+Train+Val记录

一、YOLO数据集格式分布 在YOLO中&#xff0c;数据集的分布如图&#xff0c;在dataset文件夹下有imags&#xff08;图片&#xff09;和labels&#xff08;标签&#xff09;。在images和labels文件夹下又分别存放三个文件夹&#xff0c;分别对应测试集、训练集、验证集&#xff…

记一次异步转同步的经历

工作中会经常遇到一些对数据进行加工的场景&#xff0c;这些数据来自很多地方&#xff0c;一般通过HTTP、RPC等方式去调用&#xff0c;数据源返回的报文也一般都是JSON、XML等格式。其中大部分数据源是同步返回&#xff0c;但有些数据源是异步返回的(也就是说数据源的数据是数据…

Android 音乐播放器(暂停、下一首、上一首)

1.编写主页面&#xff0c;使用listview组件放置音乐列表信息 <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/r…

使用postman测试若依其他业务接口API—3

请求方式 如上&#xff0c;使用Get请求来获取练习题库中的所有习题数据。 请求地址 在请求路径栏输入请求地址&#xff0c;以下图为例&#xff1a; 参数体与鉴权 在Parms键入所需参数&#xff0c;其中key为键,value为键的值&#xff1a;如下图所示&#xff1a; 认证成功与失…

持续集成(CICD)- gogs仓库的部署和使用

文章目录 一、gogs的介绍二、部署gog仓库三、首次启动gogs四、登录五、创建一个非空仓库六、从仓库拉取代码到本地七、把本地编辑的代码上传到仓库 一、gogs的介绍 Gogs作为一个轻量级、易于部署和使用的自托管Git服务&#xff0c;为小型团队和个人开发者提供了一个简单而强大…

【AIGC】如何提高Prompt准确度

前言 随着人工智能的迅猛进展&#xff0c;AIGC&#xff08;通用人工智能聊天工具&#xff09;已成为多个行业中不可或缺的自然语言处理技术。Prompt作为AIGC系统的一项关键功能&#xff0c;在工具的有效运作中发挥了举足轻重的作用。本篇文章将深入探讨Prompt与AIGC之间的紧密…

python笔记_程序流程控制2

C&#xff0c;循环控制 1&#xff0c;for循环 功能&#xff1a;让代码循环运行 语法&#xff1a; for <变量> in <范围、序列>&#xff1a; <循环操作语句> 例 nums &#xff08;1,2,3,4&#xff09; <class list> for i in nums&#xff1a; print&…

Java中文件的相关知识及文件IO操作

在我们日常生活中&#xff0c;会把许多东西都称之为文件。比如&#xff0c;一份纸质报告&#xff0c;或u盘中的一些文档&#xff0c;都会把它们称为文件。那么&#xff0c;这里说的文件是以操作系统的角度出发的。在操作系统中&#xff0c;会把许多硬件设备和软件资源都抽象成“…

ubuntu20.04安装nvidia驱动真实有效(被折磨了一天一夜的肝文!!!)

ubuntu20.04安装nvidia驱动真实有效 安装前后需要注意的安装nvidia驱动的教程 安装前后需要注意的 能找到这篇帖子说明你之前肯定有过无数次方法的尝试&#xff0c;这些尝试可能会影响下面教程的有效 1.下面这个指令可能会导致ubuntu内核的更新。内核更新可能会导致你的nvidia…

机器学习:主成分分析笔记

主成分分析&#xff08;Principal Component Analysis&#xff0c;PCA&#xff09;是一种无监督的机器学习算法&#xff0c;通常用于高维数据的降维、提取主要特征、数据降噪和可视化。PCA的基本思想是将原始数据的多个变量转换为少数几个相互独立的变量&#xff08;即主成分&a…