Gin增加超时控制中间件

简介: Gin增加超时控制中间件

Gin增加超时控制



背景


  • 有时候很多API有业务超时要求,就是数据必须在几秒内返回,超时的话立刻结束,不用卡死在某一个页面上。


目标


  • 对这一类API特定处理,增加超时控制,不要影响别的API


方案


  • 方案很简单,就是利用go提供的context技术对gin框架的request对象进行改造,使其具备超时控制机能。


代码:

package main
import (
 "context"
 "fmt"
 "log"
 "net/http"
 "time"
 "github.com/gin-gonic/gin"
)
// 超时控制中间件
func timeoutMiddleware(timeout time.Duration) func(c *gin.Context) {
 return func(c *gin.Context) {
  // 用超时context wrap request的context
  ctx, cancel := context.WithTimeout(c.Request.Context(), timeout)
  defer func() {
   // 检查是否超时
   if ctx.Err() == context.DeadlineExceeded {
    c.Writer.WriteHeader(http.StatusGatewayTimeout)
    c.Abort()
   }
   //清理资源
   cancel()
  }()
  // 替换
  c.Request = c.Request.WithContext(ctx)
  c.Next()
 }
}
func timedHandler(duration time.Duration) func(c *gin.Context) {
 return func(c *gin.Context) {
  // 获取替换之后的context 它具备了超时控制
  ctx := c.Request.Context()
  // 定义响应struct
  type responseData struct {
   status int
   body   map[string]interface{}
  }
  // 创建一个done chan表明request要完成了
  doneChan := make(chan responseData)
  // 模拟API耗时的处理
  go func() {
   time.Sleep(duration)
   doneChan <- responseData{
    status: 200,
    body:   gin.H{"hello": "world"},
   }
  }()
  // 监听两个chan谁先到达
  select {
  // 超时
  case <-ctx.Done():
   return
   // 请求完成
  case res := <-doneChan:
   c.JSON(res.status, res.body)
  }
 }
}
func main() {
 engine := gin.New()
 // 不用超时控制
 group := engine.Group("/normal")
 {
  group.GET("/short", timedHandler(time.Second))
 }
 // 需要超时控制 时间控制在2s
 timeoutGroup := engine.Group("/timeout")
 timeoutGroup.Use(timeoutMiddleware(time.Second * 2))
 {
  // 延迟5s
  timeoutGroup.GET("/long", timedHandler(time.Second*5))
 }
 // run the server
 log.Fatal(engine.Run(":5090"))
}


验证


  1. 正常请求

  2. 超时请求
相关文章
|
中间件
gin中间件(Use)不能写在响应函数之后的原因——源码分析
gin中间件(Use)不能写在响应函数之后的原因——源码分析
246 0
|
6月前
|
JSON 中间件 Java
【GoGin】(3)Gin的数据渲染和中间件的使用:数据渲染、返回JSON、浅.JSON()源码、中间件、Next()方法
我们在正常注册中间件时,会打断原有的运行流程,但是你可以在中间件函数内部添加Next()方法,这样可以让原有的运行流程继续执行,当原有的运行流程结束后再回来执行中间件内部的内容。​ c.Writer.WriteHeaderNow()还会写入文本流中。可以看到使用next后,正常执行流程中并没有获得到中间件设置的值。接口还提供了一个可以修改ContentType的方法。判断了传入的状态码是否符合正确的状态码,并返回。在内部封装时,只是标注了不同的render类型。再看一下其他返回的类型;
309 3
|
中间件 开发者
gin框架学习-路由分组和中间件
Logger中间件将日志写入gin.DefaultWriter,即使配置了GIN_MODE=release。
705 99
gin框架学习-路由分组和中间件
|
中间件 Go 数据格式
gin框架中间件深度解析
gin框架中间件深度解析
624 87
gin框架中间件深度解析
|
中间件
基于Gin封装Web框架 - 6. 中间件控制器
基于Gin封装Web框架 - 6. 中间件控制器
442 79
基于Gin封装Web框架 - 6. 中间件控制器
|
中间件
gin注册自定义中间件失效
gin注册自定义中间件失效
485 75
|
JSON 中间件 数据格式
Gin框架学习笔记(五) ——文件上传与路由中间件
Gin框架学习笔记(五) ——文件上传与路由中间件
307 0
|
前端开发 中间件 Java
Day05:Gin框架快速入门05 中间件和路由 | 青训营
Day05:Gin框架快速入门05 中间件和路由 | 青训营
|
消息中间件 存储 中间件
【消息中间件】详解三大MQ:RabbitMQ、RocketMQ、Kafka
【消息中间件】详解三大MQ:RabbitMQ、RocketMQ、Kafka
13829 1

热门文章

最新文章