iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >怎么优雅管理Go Project生命周期
  • 268
分享到

怎么优雅管理Go Project生命周期

2023-07-05 14:07:11 268人浏览 安东尼
摘要

这篇文章主要介绍了怎么优雅管理Go Project生命周期的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么优雅管理Go Project生命周期文章都会有所收获,下面我们一起来看看吧。一、什

这篇文章主要介绍了怎么优雅管理Go Project生命周期的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么优雅管理Go Project生命周期文章都会有所收获,下面我们一起来看看吧。

    一、什么时候要注意管理应用的生命周期?

    先来看一段代码:(假设无 err 值)

    func main() {    // 1、启动Http服务http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {fmt.Fprintln(w, "Hello, World!")})http.ListenAndServe(":8080", nil)    // 2、启动grpc服务    server := grpc.NewServer()    listener, _ := net.Listen("tcp", ":1234")server.Serve(listener)    }

    这一段代码,相信你一眼就能看出问题,因为在启动HTTP后,进程会堵塞住,下面启动GRPC服务的代码,压根就不会执行。

    但是,如果想要同时启动GRPC服务呢?该怎么做呢?

    自己没有时间,那么就请一个帮手咯,让它来为我们启动GRPC服务,而这个帮手,就是go的携程。

    • 来看一段伪代码,也就是调整成这样,

    func main() {    // 1、将HTTP服务放在后台启动    go start http    // 2、将GRPC服务放在前台启动    start grpc  }

    但是调整成这样之后,理想的情况就是,HTTP成功启动后、GRPC也要启动成功。HTTP意外退出后,GRPC也需要退出服务,他们俩需要共存亡。

    但若出现了 HTTP 意外退出、GRPC还未退出,那么就会浪费资源。还可能出现其他的问题。比如接口异常。这样会很危险。那我们该利用什么方式,让同一服务内,启动多个线程。并且让他们共同存亡的呢?

    了解了上面的问题,我们再来重新描述总结一下出现的问题。

    一个服务,可能会启动多个进程,比如说 HTTP api、GRPC API、服务的注册,这些模块都是独立的,都是需要在程序启动的时候进行启动。

    而且如果需要关闭掉这个应用,还需要处理很多关闭的问题。比如说

    • HTTP、GRPC 的优雅关闭

    • 关闭数据库链接

    • 完成注册中心的注销操作

    • ...

    而且,启动的多个进程间,该如何通信呢? 某些服务意外退出了,按理来说要关闭整个应用,该如何监听到呢?

    二、我们是如何做的

    (1)利用面向对象的方式来管理应用的生命周期

    定义一个管理者对象,来管理我们应用所需要启动的所有服务,比如这里需要被我们启动的服务有:HTTP、GRPC

    这个管理者核心有两个方法:start、stop

    // 用于管理服务的开启、和关闭type manager struct {http *protocol.httpservice // HTTP生命周期的结构体[自定义]grpc *protocol.GRPCService // GRPC生命周期的结构体[自定义]l    logger.Logger   // 日志对象}

    不用关心这里依赖的 http、grpc结构体是什么,我们在后面的章节,会详细解释。只需要知道,我们用manager这个结构体,用于管理http、grpc服务即可。

    (2)处理start

    start这个函数,核心只做了两件事,分别启动HTTP、GRPC服务。

    func (m *manager) start() error {// 打印加载好的服务m.l.Infof("已加载的 [Internal] 服务: %s", ioc.ExistingInternalDependencies())m.l.Infof("已加载的 [GRPC] 服务: %s", ioc.ExistingGrpcDependencies())m.l.Infof("已加载的 [HTTP] 服务: %s", ioc.ExistingGinDependencies())// 如果不需要启动HTTP服务,需要才启动HTTP服务if m.http != nil {// 将HTTP放在后台跑go func() {// 注:这属于正常关闭:"http: Server closed"if err := m.http.Start(); err != nil && err.Error() != "http: Server closed" {return}}()}    // 将GRPC放入前台启动m.grpc.Start()return nil}

    又因为开头说过了,启动这两任一服务,都会将进程堵塞住。

    所以我们找了一个帮手(携程)来启动HTTP服务,然后将GRPC服务放在前台运行。

    那为什么我要将GRPC服务放在前台运行呢?其实理论上放谁都行,但由于我们的架构原因。我们有的服务不需要启动HTTP服务,而每一个服务都会启动GRPC服务。所以,将GRPC放置在前台,会更合适。

    至于里面如何使用HTTP、GRPC的服务对象启动它们的服务。在这一节就不多赘述了。在之后的章节会有详细的介绍~

    看完了统一管理启动的start方法,那我们来看看如何停止服务吧

    (3)处理stop

    1、什么时候才去Stop?

    我们开启了多个服务,并且有的还是放在后台运行的。这就涉及到了多个携程的间通信的问题了

    用什么来通信吶?我怎么知道HTTP服务挂没挂?是意外挂的还是主动挂的?我们怎么能够优雅的统一关闭所有服务呢?

    其实这一切的问题,Go都为我们想好了:那就是使用Channels。一个channel是一个通信机制,它可以让一个携程通过它给另一个携程发送值信息。每个channel都有一个特殊的类型,也就是channels可发送数据的类型。

    我们把一个go程当作一个人的化,那么main 方法启动的主go程就是你自己。在你的程序中使用到的其他go程,都是你的好帮手,你的好朋友,它们有给你去处理耗时逻辑的、有给你去执行业务无关的切面逻辑的。而且是你的好帮手,按理来说最好是由你自己去决定,要不要请一个好帮手。

    当你请来了一个好帮手后,它们会在你的背后为你做你让他们做的事情。那么多个人之间的通信,比较现代的方法,那可以是:打个电话?发个消息?所以用到了一个沟通的信道:Channel

    好了,当你了解了这些后,也就是接收到一些电话后,我们才需要去stop。我们再回到Dousheng使用的情景:

    2、Dousheng的应用场景

    主携程是GRPC服务这个人,我们请了一个帮手,给我启动HTTP服务。这个时候,如果HTTP服务这个帮手意外出事了。既然是帮我么你做事,那我们肯定得对别人负责是吧。但是我们也不知道它出不出意外啊,怎么办呢?这时候你想了两个方法:

    • 跟你的帮手HTTP,发了如下消息

    怎么优雅管理Go Project生命周期

    这就需要HTTP自己告诉我们,按理来说,应该是可以的。但是如果HTTP遇到了重大问题,根本来不及告诉我们呢?咱们又是一个负责的男人。为了避免这种情况发生,又请一个人,专门给我们看HTTP有没有遇到重大问题。于是有了第二种方式:

    • 在请一个帮手signal.Notify,帮助我们监听HTTP可能会遇到的重大问题

    怎么优雅管理Go Project生命周期

    当我们收到HTTP出事的信号后,那我们就可以统一的去优雅关闭服务了。就这样,我们做了一个负责的人~

    相信你已经了解了核心的思想,我们来看看,用代码该如何实现

    3、代码实现
    • 启动signal.Notify,用于监听系统信号

    我们已经分析过了,我们需要再请一个帮手,来给我们处理HTTP可能会遇到的重大事故:(syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP, syscall.SIGINT)

    // WaitSign 等待退出的信号,实现优雅退出func (m *manager) waitSign() {   // 用于接收信号的信道   ch := make(chan os.Signal, 1)   // 接收这几种信号   signal.Notify(ch, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP, syscall.SIGINT)   // 需要在后台等待关闭   go m.waitStop(ch)}

    signal.Notify收到上面所列举的信号后,那么就可以去做关闭的事情了,那如何关闭呢?

    • 读取信号,执行优雅关闭逻辑

    // WaitStop 中断信号,比如Terminal [关闭服务的方法]func (m *manager) waitStop(ch <-chan os.Signal) {   // 等待信号,若收到了,我们进行服务统一的关闭   for v := range ch {      switch v {      default:         m.l.Infof("接受到信号:%s", v)         // 优雅关闭HTTP服务         if m.http != nil {            if err := m.http.Stop(); err != nil {               m.l.Errorf("优雅关闭 [HTTP] 服务出错:%s", err.Error())            }         }// 优雅关闭GRPC服务         if err := m.grpc.Stop(); err != nil {            m.l.Errorf("优雅关闭 [GRPC] 服务出错:%s", err.Error())         }      }   }}

    这里的逻辑比较简单,就是当接收到信号的时候,对HTTP、GRPC做优雅关闭的逻辑。至于为什么要进行优雅关闭,而不是直接os.Exit()?我们在下一节讲~

    这里值得一提的是,我们从chanel里获取数据,因为我们这里只和单个携程间进行通信了,使用的是 for range,并没有使用for select

    好了,这样我们应用的生命周期算是被我们优雅的拿捏了。我们一直在讲优雅关闭这个词,我们来解释一下什么是优雅关闭?为什么需要优雅关闭?

    三、什么是优雅关闭

    既然HTTP服务和GRPC服务都需要优雅关闭,我们这里用HTTP服务来举例。

    先来看这张图,假设有三个并行的请求至我们的HTTP服务。它们都期望得到服务器response。HTTP服务器正常运行的情况下,多半是没问题的。

    怎么优雅管理Go Project生命周期

    请求已发出,若提供的HTTP服务突然异常关闭了呢?我们继续来把HTTP服务比作一个人。看看它是否优雅呢?

    (1)没有优雅关闭

    如果HTTP这个人不太优雅,是一个做事不怎么负责的渣男。当自己异常over了之后,也不解决完自己的事情,就让别人(request),找不到资源了。真的很不负责啊。

    大致用一幅图表示:

    怎么优雅管理Go Project生命周期

    这个不优雅的HTTP服务,当有还未处理的请求时,自己就异常关闭了,那么它根本不会理会原先的请求是否完成了。它只管自己退出程序。

    (2)有了优雅关闭

    看完了那个渣男HTTP(没有优雅关闭),我们简直想骂它了。那我们来看,当一个优雅的谦谦君子(有优雅关闭),又是如何看待这个问题的。

    怎么优雅管理Go Project生命周期

    这是一个负责人的人,为什么说他负责人、说它优雅呢?因为当它自己接收到异常关闭的信号后。它不会只顾自己关闭。它大概还会做两件事:

    • 关闭建立连接的请求通道,防止还会接收到新的请求

    • 处理完以请求的,但是还未响应的请求。保证资源得到响应,哪怕是错误的response

    正是因为它主要做了这两件事,我们才说此时的HTTP服务,是一个优雅的谦谦君子。

    而当有很多个请求到时候,我们怎么知道是否会不会突然异常关闭呢?如果遇到了这种情况,我们应该处理完未完成的响应,拒绝新的请求建立连接,因为我们是一个优雅的人。

    关于“怎么优雅管理Go Project生命周期”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“怎么优雅管理Go Project生命周期”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网精选频道。

    --结束END--

    本文标题: 怎么优雅管理Go Project生命周期

    本文链接: https://www.lsjlt.com/news/352242.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • 优雅管理Go Project生命周期
      目录写在前面 一、什么时候要注意管理应用的生命周期?二、我们是如何做的(1)利用面向对象的方式来管理应用的生命周期(2)处理start(3)处理stop1、什么时候才去St...
      99+
      2023-03-20
      Go Project生命周期 Go Project项目管理
    • 怎么优雅管理Go Project生命周期
      这篇文章主要介绍了怎么优雅管理Go Project生命周期的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么优雅管理Go Project生命周期文章都会有所收获,下面我们一起来看看吧。一、什...
      99+
      2023-07-05
    • 如何在 Go 中管理 Goroutine 的生命周期?
      非常抱歉,由于您没有提供文章标题,我无法为您生成一篇高质量的文章。请您提供文章标题,我将尽快为您生成一篇优质的文章。...
      99+
      2024-05-16
    • JavaSpringBean的生命周期管理详解
      目录Spring Bean的生命周期管理一、Spring Bean的生命周期二、通过@Bean的参数(initMethod ,destroyMethod)指定Bean的初始化和销毁方...
      99+
      2024-04-02
    • Vue生命周期怎么理解
      这篇“Vue生命周期怎么理解”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue生命周期怎么理解”文章吧。1、定义生命周期函...
      99+
      2023-07-06
    • Golang异常处理的生命周期管理
      异常处理生命周期管理在 go 中至关重要,用于处理错误情况。它包含以下阶段:异常发生:通常由 panic() 触发。查找异常处理程序:系统在调用栈中查找处理当前异常类型的处理程序。执行异...
      99+
      2024-04-16
      生命周期 异常处理 golang
    • 怎么理解java线程生命周期
      本篇内容主要讲解“怎么理解java线程生命周期”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解java线程生命周期”吧!线程生命周期的几种状态刚接触线程生命周期时,我总是记不住,也理解不了...
      99+
      2023-06-16
    • Golang函数生命周期中的内存管理
      go 函数生命周期内,内存管理按以下步骤进行:函数调用时创建堆栈帧,用于存储局部变量等信息。函数返回时销毁堆栈帧,释放该内存。分配超过 32kb 数据时,内存分配至堆上并由垃圾回收器管理...
      99+
      2024-04-18
      golang 内存管理 垃圾回收器
    • 怎样理解Spring Bean生命周期
      怎样理解Spring Bean生命周期,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。在网上已经有跟多Bean的生命周期的博客,但是很多都是基于比较老的版本了,最近把整个流程...
      99+
      2023-06-16
    • vue生命周期怎么掌握
      本篇内容介绍了“vue生命周期怎么掌握”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!根实例的加载相关的生命周期(beforeCreate、c...
      99+
      2023-07-04
    • Java Spring Bean生命周期管理的示例分析
      小编给大家分享一下Java Spring Bean生命周期管理的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!Spring Bean的生命周期管理一、Spring Bean的生命周期通过以下方式...
      99+
      2023-06-22
    • Go语言变量的生命周期是什么
      这篇文章主要介绍了Go语言变量的生命周期是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Go语言变量的生命周期是什么文章都会有所收获,下面我们一起来看看吧。在Go语言中,变量的生命周期指的是在程序运行期间变...
      99+
      2023-07-04
    • FESCAR管理分布式事务的生命周期是什么
      这篇文章主要介绍“FESCAR管理分布式事务的生命周期是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“FESCAR管理分布式事务的生命周期是什么”文章能帮助大家解决问题。什么是FESCAR?一种...
      99+
      2023-06-29
    • CPython 与内存管理:深入理解 Python 对象生命周期
      ...
      99+
      2024-04-02
    • Docker | Docker技术基础梳理(三) - 容器生命周期管理
      什么是容器?容器(Container):容器是一种轻量级、可移植、并将应用程序进行的打包的技术,使应用程序可以在几乎任何地方以相同的方式运行,Docker将镜像文件运行起来后,产生的对象就是容器。容器相当于是镜像运行起来的一个实例且容器具备...
      99+
      2023-06-04
    • JSP中生命周期是怎么样的
      这篇文章主要介绍了JSP中生命周期是怎么样的,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。JSP 生命周期理解JSP底层功能的关键就是去理解它们所遵守的生命周期。JSP生命周...
      99+
      2023-06-02
    • 探讨数据在Hadoop中的生命周期管理策略
      Hadoop中的数据生命周期管理策略是指对数据在Hadoop集群中的存储、访问和处理过程进行管理和优化的一种策略。以下是一些常见的数...
      99+
      2024-02-29
      Hadoop
    • Android  Activity生命周期和堆栈管理的详解
      Activity的生命周期Activity是Android中的四大组件之一,也是最基本,最重要的组件,是android系统提供一个可视化的,能与用户交换的组件。 系统提供的组件,不需要用户实例化,用户也不能实例化,是系统进行回调,例如web...
      99+
      2023-05-30
      android activity 生命周期
    • 怎么理解微信小程序中的生命周期
      本篇内容主要讲解“怎么理解微信小程序中的生命周期”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解微信小程序中的生命周期”吧!一、生命周期1. 什么是生命周期?生命周期 (Life Cycl...
      99+
      2023-06-25
    • react的生命周期函数怎么使用
      这篇文章主要介绍“react的生命周期函数怎么使用”,在日常操作中,相信很多人在react的生命周期函数怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”react的生命周期函数怎么使用”的疑惑有所帮助!...
      99+
      2023-07-04
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作