Fork me on GitHub

版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | https://vearne.cc

前言

gin底层使用的是net/http, 所以gin的优雅退出就等于
http.Server的优雅退出, Golang 1.8以后提供了Shutdown函数,可以优雅关闭http.Server

func (srv *Server) Shutdown(ctx context.Context) error

优雅退出的过程

  • 1)关闭所有的监听
  • 2)后关闭所有的空闲连接
  • 3)无限期等待活动的连接处理完毕转为空闲,并关闭
    如果提供了带有超时的Context,将在服务关闭前返回 Context的超时错误

完整的例子

package main

import (
    "net/http"
    "time"
    "os"
    "os/signal"
    "syscall"
    "fmt"
    "github.com/gin-gonic/gin"
    "github.com/pkg/errors"
)

func SlowHandler(c *gin.Context) {
    fmt.Println("[start] SlowHandler")
    //time.Sleep(30 * time.Second)
    time.Sleep(30 * time.Second)
    fmt.Println("[end] SlowHandler")
    c.JSON(http.StatusOK, gin.H{

        "message": "success",
    })
}

// 实现context.Context接口
type ExitContext struct{
    Chan chan struct{}
    DeadLineTime time.Time
}

func NewExitContext(duration time.Duration) *ExitContext{
    cxt :=  ExitContext{}
    cxt.DeadLineTime = time.Now().Add(duration)
    cxt.Chan = make(chan struct{}, 1)
    return &cxt
}

func (cxt *ExitContext) Done() <-chan struct{}{
    if time.Now().After(cxt.DeadLineTime){
        cxt.Chan <- struct{}{}
    }
    return cxt.Chan
}


func (cxt *ExitContext) Err() error{
    return errors.New("can't exit before Specified time")
}

// 无意义的空函数
func(cxt *ExitContext) Value(key interface{}) interface{}{
    return nil
}

func(ctx *ExitContext) Deadline() (deadline time.Time, ok bool){
    deadline = ctx.DeadLineTime
    ok = true
    return
}

func main() {
    r := gin.Default()
    // 1.
    r.GET("/slow", SlowHandler)


    server := &http.Server{
        Addr:           ":8080",
        Handler:        r,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }

    go server.ListenAndServe()
    // 设置优雅退出
    gracefulExitWeb(server)
}

func gracefulExitWeb(server *http.Server) {
    ch := make(chan os.Signal)
    signal.Notify(ch, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT)
    sig := <-ch

    fmt.Println("got a signal", sig)
    now := time.Now()
    cxt := NewExitContext(3*time.Second)
    err := server.Shutdown(cxt)
    if err != nil{
        fmt.Println("err", err)
    }

    // 看看实际退出所耗费的时间
    fmt.Println("------exited--------", time.Since(now))
}

更简单的写法

package main

import (
    "net/http"
    "time"
    "os"
    "os/signal"
    "syscall"
    "fmt"
    "github.com/gin-gonic/gin"
    "context"
)

func SlowHandler(c *gin.Context) {
    fmt.Println("[start] SlowHandler")
    //time.Sleep(30 * time.Second)
    time.Sleep(30 * time.Second)
    fmt.Println("[end] SlowHandler")
    c.JSON(http.StatusOK, gin.H{

        "message": "success",
    })
}


func main() {
    r := gin.Default()
    // 1.
    r.GET("/slow", SlowHandler)


    server := &http.Server{
        Addr:           ":8080",
        Handler:        r,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }

    go server.ListenAndServe()
    // 设置优雅退出
    gracefulExitWeb(server)
}

func gracefulExitWeb(server *http.Server) {
    ch := make(chan os.Signal)
    signal.Notify(ch, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT)
    sig := <-ch

    fmt.Println("got a signal", sig)
    now := time.Now()
    cxt, cancel := context.WithTimeout(context.Background(), 5 * time.Second)
    defer cancel()
    err := server.Shutdown(cxt)
    if err != nil{
        fmt.Println("err", err)
    }

    // 看看实际退出所耗费的时间
    fmt.Println("------exited--------", time.Since(now))
}

参考资料1中的例子有错误
如果context 被设置为nil,程序实际是异常崩溃了

log.Println(s.Shutdown(nil))

参考资料

1.Go 1.8 http graceful 体验
2.Gin实践 连载七 Golang优雅重启HTTP服务

后记

萌叔写了一个方便管理多个worker,轻松启动停止的库,欢迎使用
vearne/worker_manager


请我喝瓶饮料

微信支付码

7 对 “gin 优雅退出”的想法;

  1. go server.ListenAndServe()
    请问这里的服务为什么放在协程中呢,刚入门go,看到好多地方都这样写,但没搞清楚为什么

    1. server.ListenAndServe()
      本身会监听在socket上,如果不放到另一个协程中,
      后面的代码

         // 设置优雅退出
          gracefulExitWeb(server)
      

      是无法被执行到的

  2. One X Bet Bonus Code – Exclusive Bonus as much as 130 Euros
    Use the One X Bet promo code: Code 1XBRO200 while signing up in the App to access special perks given by 1xBet to receive 130 Euros as much as 100%, for placing bets plus a $1950 including one hundred fifty free spins. Start the app then continue with the registration procedure.
    The One X Bet bonus code: 1xbro200 gives a great sign-up bonus for first-time users — 100% maximum of 130 Euros during sign-up. Bonus codes act as the key to obtaining extra benefits, also One X Bet’s promo codes are the same. By using such a code, players can take advantage of several promotions throughout their journey in their gaming adventure. Even if you aren’t entitled for the welcome bonus, 1xBet India makes sure its regular customers get compensated with frequent promotions. Check the Promotions section on the site regularly to remain aware on the latest offers meant for current users.
    1xbet official promo code
    Which One X Bet bonus code is presently available right now?
    The promotional code for 1xBet is 1XBRO200, enabling first-time users signing up with the betting service to gain a bonus worth 130 dollars. For gaining unique offers pertaining to gaming and wagering, kindly enter our bonus code for 1XBET during the sign-up process. To take advantage of this offer, future players should enter the promo code 1XBET at the time of registering procedure for getting a 100% bonus for their first payment.

  3. Within this platform, explore a variety internet-based casino sites.
    Interested in traditional options latest releases, there’s something for any taste.
    The listed platforms checked thoroughly for safety, so you can play with confidence.
    gambling
    What’s more, the site offers exclusive bonuses along with offers to welcome beginners including long-term users.
    Due to simple access, locating a preferred platform happens in no time, saving you time.
    Stay updated about the latest additions through regular check-ins, as fresh options appear consistently.

  4. Здесь доступны видеообщение в реальном времени.
    Если вы ищете дружеское общение переговоры, на платформе представлены решения для каждого.
    Функция видеочата создана для связи людей со всего мира.
    видео секс чат
    С высококачественным видео и превосходным звуком, вся беседа становится увлекательным.
    Вы можете присоединиться к публичным комнатам общаться один на один, опираясь на ваших предпочтений.
    Все, что требуется — надежная сеть и совместимое устройство, и вы сможете подключиться.

  5. Здесь вы можете найти видеообщение в реальном времени.
    Вы хотите непринужденные разговоры переговоры, на платформе представлены варианты для всех.
    Модуль общения предназначена чтобы объединить пользователей глобально.
    секс чат рулетка пары
    За счет четких изображений и превосходным звуком, любое общение становится увлекательным.
    Войти в общий чат общаться один на один, опираясь на ваших потребностей.
    Для начала работы нужно — надежная сеть и любое поддерживаемое устройство, и вы сможете подключиться.

  6. This website, you can discover lots of online slots from top providers.
    Visitors can experience retro-style games as well as new-generation slots with stunning graphics and interactive gameplay.
    Even if you’re new or a seasoned gamer, there’s always a slot to match your mood.
    play bonanza
    All slot machines are available anytime and designed for laptops and tablets alike.
    You don’t need to install anything, so you can jump into the action right away.
    Site navigation is user-friendly, making it quick to explore new games.
    Join the fun, and discover the thrill of casino games!

回复 секс видеочат 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注