如何优雅的关闭GoWeb服务器

以下内容均为Let’s Go Further内容节选以及作者本人理解。
这里创建了一个后台进程用于捕获关闭信号,在后台进程中,主要内容为:

  1. 创建一个缓冲通道 quit
  2. 使用signal.Notify函数监听并捕获关机信号SIGINT,SIGTERM,在捕获关机信号后,缓冲通道取值操作才会执行,取消阻塞。
  3. 随后使用shutdown函数关闭服务器。工作原理是首先关闭所有打开的侦听器,然后关闭所有空闲连接,然后无限期地等待连接返回空闲状态,然后关闭。
  4. 如果关闭连接时发生错误,则将错误存储进入通道,主程序取出错误,取消阻塞。返回错误。
  5. 如果正常关闭连接,app.wg.Wait()等待全部后台进程全部运行结束后放行,随后向错误通道存储空值,放行主程序。此时连接和后台进程全部关闭,打印日志,结束。
package mainimport ("context""errors""fmt""net/http""os""os/signal""syscall""time"
)func (app *application) serve() error {srv := http.Server{Addr:         fmt.Sprintf(":%d", app.config.port),Handler:      app.routes(),IdleTimeout:  time.Minute,ReadTimeout:  10 * time.Second,WriteTimeout: 30 * time.Second,//服务器可以编写自己的日志消息,实现Write方法变成io.Write接口可以将自定义日志传递进去//ErrorLog: log.New(logger, "", 0),}shutdownErr := make(chan error)//开启一个后台进程 捕获关闭信号,关闭所有连接和后台进程,实现优雅的关机go func() {//创建一个通道保存os.Signal值/*在这里使用缓冲通道,如果使用非缓冲通道,quit 通道 在信号发送的时刻没有准备去接收,会错过信号*/quit := make(chan os.Signal, 1)//使用signal.Notify监听SIGINT and SIGTERM信号并将他们传入quit通道。其他信号不会被捕获并保留他们默认的行为。signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)//从通道中读取值,这个操作将被阻塞直到通道接收一个值s := <-quitapp.logger.PrintInfo("shutting down server", map[string]string{"signal": s.String(),})//创建一个5秒的上下文ctx, cancelFunc := context.WithTimeout(context.Background(), 5*time.Second)defer cancelFunc()//服务调用shutdown,如果成功关闭将返回nil,或者返回错误(当关闭一个监听器时遇到问题,或者在到达截止日期时没有完成)/*工作原理是首先关闭所有打开的侦听器,然后关闭所有空闲连接,然后无限期地等待连接返回空闲状态,然后关闭。*//*1. 关闭连接时没有返回错误,说明连接全部关闭,但是还有后台进程,告诉正在执行关闭后台进程,需要等待wg归零。2. 关闭连接出现错误。将err存入通道,放行主程序*///shutdown返回的是一个error类型的变量err := srv.Shutdown(ctx)//通道中存入错误,主程序取消阻塞,继续执行if err != nil {shutdownErr <- err}//正在完成后台进程app.logger.PrintInfo("completing background tasks", map[string]string{"addr": srv.Addr,})app.wg.Wait()//后台进程全部关闭后,放行主程序shutdownErr <- nil}()app.logger.PrintInfo("starting server", map[string]string{"addr": srv.Addr,"env":  app.config.env,})//调用shutdown会造成ListenAndServer立刻返回一个http.ErrServerClosed错误。如果是这个错误,表明我们的程序优雅的关闭了err := srv.ListenAndServe()if !errors.Is(err, http.ErrServerClosed) {return err}//阻塞  关闭后才能继续执行err = <-shutdownErrif err != nil {return err}app.logger.PrintInfo("stopped server", map[string]string{"addr": srv.Addr,})return nil
}

关于使用后台进程运行其他任务时,使用函数background来启动后台进程

func (app *application) background(fn func()) {//开启一个后台进程app.wg.Add(1)go func() {defer app.wg.Done()//使用延迟函数捕获可能出现的panicdefer func() {if err := recover(); err != nil {app.logger.PrintError(fmt.Errorf("%s", err), nil)}}()fn()}()
}

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

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

相关文章

入侵他人电脑,实现远程控制(待补充)

待补充 在获取他人无线网网络密码后&#xff0c;进一步的操作是实现入侵他人电脑&#xff0c;这一步需要获取对方的IP地址并需要制作自己的代码工具自动化的开启或者打开对方的远程访问权限。 1、获取IP地址&#xff08;通过伪造的网页、伪造的Windows窗口、hook&#xff0c;信…

mac 安装graalvm

Download GraalVM 上面链接选择jdk的版本 以及系统的环境下载graalvm的tar包 解压tar包 tar -xzf graalvm-jdk-<version>_macos-<architecture>.tar.gz 移入java的文件夹目录 sudo mv graalvm-jdk-<version> /Library/Java/JavaVirtualMachines 设置环境变…

[SZ901]JTAG高速下载设置(53Mhz)

SZ901最高支持JTAG 53MHz的时钟频率&#xff0c;下载bit文件和固化程序的速度提升非常明显。 首先设置参数 1&#xff0c;将JTAG0 分频系数修改为3 2&#xff0c;设置参数&#xff0c;更新参数。&#xff08;完成&#xff09; 打开VIVADO VIVADO 正常识别FPGA&#xff0c;速…

蓝桥杯刷题——day8

蓝桥杯刷题——day8 题目一题干解题思路代码 题目二题干解题思路代码 题目一 题干 N 架飞机准备降落到某个只有一条跑道的机场。其中第i架飞机在 Ti时刻到达机场上空&#xff0c;到达时它的剩余油料还可以继续盘旋 Di个单位时间&#xff0c;即它最早可以于 Ti时刻开始降落&am…

深度科普文:细数倾斜摄影数据的缺点

1. 引言 写这篇文章的起因是最近遇到一个使用倾斜摄影数据应标的三维可视化项目&#xff0c;业主认为倾斜摄影数据加载很卡&#xff0c;要求能浏览场景的时候能立刻显示出当前的场景最精细的模型&#xff0c;如下图1所示。其实这个问题遇到的次数还真不少&#xff0c;作为乙方…

React:闭包陷阱产生和解决

在 React 中&#xff0c;闭包陷阱是一个常见的问题&#xff0c;尤其是在处理异步操作、事件处理器、或是定时器时。理解闭包的工作原理以及它在 React 中如何与状态和渲染交互&#xff0c;可以帮助你避免陷入一些常见的错误。 一、闭包陷阱的产生 1、什么是闭包陷阱&#xff1…

【开源免费】基于SpringBoot+Vue.JS在线宠物用品交易网站(JAVA毕业设计)

本文项目编号 T 092 &#xff0c;文末自助获取源码 \color{red}{T092&#xff0c;文末自助获取源码} T092&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

【Git 常用操作:pull push】

Git 基本概念 Git 是一个先进的开源的分布式版本控制系统&#xff0c;常用于管理工作内容、项目代码等功能。 Git 工作流程 图片来源&#xff1a;https://www.runoob.com/git/git-basic-operations.html 说明&#xff1a; workspace&#xff1a;工作区staging area&#xff…

shell脚本的循环-----while和for循环

一、while 1.格式 while 条件表达式; do 命令 done 2.案例 &#xff1a; ping测试子网段的主机网段由用户输入&#xff0c;例如用户输入192.168.101 &#xff0c;则ping192.168.101.125 — 192.101.131 UP&#xff1a; /tmp/host_up.txt Down: /tmp/host_down.txt &#…

内容与资讯API优质清单

作为开发者&#xff0c;拥有一套API合集是必不可少的。这个开发者必备的API合集汇集了各种实用的API资源&#xff0c;为你的开发工作提供了强大的支持&#xff01;无论你是在构建网站、开发应用还是进行数据分析&#xff0c;这个合集都能满足你的需求。你可以通过这些免费API获…

maven-resources-production:ratel-fast: java.lang.IndexOutOfBoundsException

Maven生产环境中遇到java.lang.IndexOutOfBoundsException的问题&#xff0c;尝试了重启电脑、重启IDEA等常规方法无效&#xff0c;最终通过直接重建工程解决了问题。 Rebuild Project 再启动OK

[数据结构] 链表

目录 1.链表的基本概念 2.链表的实现 -- 节点的构造和链接 节点如何构造? 如何将链表关联起来? 3.链表的方法(功能) 1).display() -- 链表的遍历 2).size() -- 求链表的长度 3).addFirst(int val) -- 头插法 4).addLast(int val) -- 尾插法 5).addIndex -- 在任意位置…

深度学习0-前置知识

一、背景 AI最大&#xff0c;它的目的是通过让机器模仿人类进而超越人类&#xff1b; ML次之&#xff0c;它是AI的一个分支&#xff0c;是让机器模仿人类的一种方法。开发人员用大量数据和算法“训练”机器&#xff0c;让机器自行学会如何执行任务&#xff0c;它的成功取决于…

基于Python Scrapy的豆瓣Top250电影爬虫程序

Scrapy安装 Python实现一个简单的爬虫程序&#xff08;爬取图片&#xff09;_python简单扒图脚本-CSDN博客 创建爬虫项目 创建爬虫项目&#xff1a; scrapy startproject test_spider 创建爬虫程序文件&#xff1a; >cd test_spider\test_spider\spiders >scrapy g…

LabVIEW中的“Synchronize with Other Application Instances“

在LabVIEW中&#xff0c;“Synchronize with Other Application Instances”是一个常见的提示或错误&#xff0c;通常出现在尝试并行运行多个LabVIEW实例时&#xff0c;特别是当你打开多个VI或项目时。这个问题可能影响程序的执行流程&#xff0c;导致不同实例之间的数据同步或…

【Linux】AlmaLinux 9.5虚拟机安装过程记录分享

关于AlmaLinux系统感兴趣的&#xff0c;可以去我之前写的另外一篇博客里面看看&#xff1a; https://blog.csdn.net/cnskylee/article/details/143142690 语言&#xff0c;选择【简体中文&#xff08;中国&#xff09;】&#xff0c;点击【继续】&#xff0c;进入后续设置 在…

深度学习——现代卷积神经网络(七)

深度卷积神经网络 学习表征 观察图像特征的提取⽅法。在合理地复杂性前提下&#xff0c;特征应该由多个共同学习的神经⽹络层组成&#xff0c;每个层都有可学习的参数。 当年缺少数据和硬件支持 AlexNet AlexNet⽐相对较⼩的LeNet5要深得多。 AlexNet由⼋层组成&#xff1a…

时间管理系统|Java|SSM|JSP|

【技术栈】 1⃣️&#xff1a;架构: B/S、MVC 2⃣️&#xff1a;系统环境&#xff1a;Windowsh/Mac 3⃣️&#xff1a;开发环境&#xff1a;IDEA、JDK1.8、Maven、Mysql5.7 4⃣️&#xff1a;技术栈&#xff1a;Java、Mysql、SSM、Mybatis-Plus、JSP、jquery,html 5⃣️数据库可…

20241217使用M6000显卡在WIN10下跑whisper来识别中英文字幕

20241217使用M6000显卡在WIN10下跑whisper来识别中英文字幕 2024/12/17 17:21 缘起&#xff0c;最近需要识别法国电影《地下铁》的法语字幕&#xff0c;使用 字幕小工具V1.2【whisper套壳/GUI封装了】 无效。 那就是直接使用最原始的whisper来干了。 当你重装WIN10的时候&#…

PostgreSQL技术内幕21:SysLogger日志收集器的工作原理

0.简介 在前面文章中介绍了事务模块用到的事务日志结构和其工作原理&#xff0c;本文将介绍日志的另一个部分&#xff0c;操作日志&#xff0c;主要去描述SysLogger日志的工作原理&#xff0c;流程以及其中关键的实现&#xff1a;日志轮转&#xff0c;刷盘性能问题等&#xff…