当前位置:   article > 正文

go | gin多服务 | goroutine | ReadTimeout&WriteTimeout_writetimeoutexample

writetimeoutexample

采用 go 的协程完成 gin多服务
什么多服务?就是启动服务器后,可以同时访问多个资源,比如router01、router02
ReadTimeout 读取请求超时时间,一般防止客户端慢请求,导致长时间占用服务器资源
WriteTimeout 写入响应超时时间,一般是防止客户端读取响应慢,导致长时间占用服务器资源

可以这么理解,就是服务器这边的效率是特别高的,出现的问题都是从客户端那边冒出来的
然后,服务器要读取来自客户端的请求 所有叫ReadTimeout 读取请求超时时间,这个是从客户端从开始发起请求到结束发起请求结束的时间,如果一个请求数据,一直慢吞吞的发送,这个时间段服务器其实是中断来处理这个业务的,这个时间段的资源全部用来等待请求数据,是不是占用了很多资源?
WriteTimeout 叫写入响应超时时间,就是服务器要响应客户端的请求,如果客户端读取服务器的响应很慢,水管那头(客户端)一直减速,水管这头(服务器)的写入速度是不是也响应的被减缓了?

package main

import (
	"log"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"golang.org/x/sync/errgroup"
)

var (
	g errgroup.Group
)

func route01() http.Handler {
	e := gin.New()
	e.Use(gin.Recovery())
	e.GET("/", func(c *gin.Context) {
		c.JSON(
			http.StatusOK,
			gin.H{
				"code":  http.StatusOK,
				"error": "wellcome server 01",
			},
		)
	})
	return e
}

func router02() http.Handler {
	// 创建一个新的Gin引擎
	e := gin.New()
	// 为这个引擎添加一个中间件,它可以捕获处理请求过程中的任何panic并将错误写入日志
	e.Use(gin.Recovery())
	// 为这个引擎添加一个GET 路由,当收到这个请求时,调用处理函数
	e.GET("/", func(c *gin.Context) {
		// c.JSON 是一个方法,生成JSON格式的HTTP响应
		c.JSON(
			http.StatusOK,
			gin.H{
				"code":  http.StatusOK,
				"error": "wellcome server02",
			},
		)
	})
	return e
}

/*
		go run example_14_runservers.go
		example_14_runservers.go:9:2: no required module provides package golang.org/x/sync/errgroup; to add it:
	    go get golang.org/x/sync/errgroup
		[root@localhost gin_test]# go get golang.org/x/sync/errgroup
*/
func main() {
	server01 := &http.Server{
		Addr:         ":8080",
		// Handler 接收所有的HTTP请求
		Handler:      route01(),	
		// ReadTimeout 读取请求的超时时间		防止慢速攻击(客户端故意以非常慢的速度发送请求,导致服务器资源被长时间占用)	
		ReadTimeout:  5 * time.Second,
		//WriteTimeout 写入响应的超时时间		防止客户端读取响应过慢,导致服务器资源被长时间占用
		WriteTimeout: 10 * time.Second,
	}

	server02 := &http.Server{
		Addr:         ":8081",
		Handler:      router02(),
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
	}
	// 会在新的goroutine中启动服务器
	//server02.ListenAndServe() 是 Go 语言 net/http 包中 Server 结构体的一个方法。
	//这个方法会启动一个 HTTP 服务器,使其开始监听其 Addr 字段指定的网络地址,并等待并处理接收到的 HTTP 请求。

	//当我们说 server02.ListenAndServe() 会阻塞 goroutine,意思是这个方法会一直运行,
	//直到服务器停止。在这个方法运行期间,它所在的 goroutine 不会执行其他代码,也就是说,这个 goroutine 被 "阻塞" 了。
	g.Go(func() error {
		return server01.ListenAndServe()
	})

	g.Go(func() error {
		return server02.ListenAndServe()
	})

	/*
		等待由group启动的所有goroutine结束
		收集gorountine 出现的错误
		调用 g.wait的goroutine会阻塞,等待所有的g.Go启动后的goroutine结束。
		只有所有的g.Go启动的goroutine结束之后,才执行g.wait收集错误
	*/
	if err := g.Wait(); err != nil {
		log.Fatal("the err is ", err)
	}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
轻量级:goroutine 是非常轻量级的,它的创建和切换的开销都非常小。一个 Go 程序可以同时运行数十万甚至数百万个 goroutine,而在大多数操作系统上,同时运行这么多的线程是不可能的。

内存占用:每个 goroutine 的堆栈大小开始时非常小(只有几 KB),并且可以根据需要增长和缩小,而线程的堆栈大小通常是固定的,通常为几 MB。

调度:goroutine 的调度是由 Go 运行时进行的,而不是由操作系统进行的。这意味着 Go 运行时可以更精细地控制 goroutine 的执行,例如,当一个 goroutine 在等待 I/O 操作时,Go 运行时可以运行其他 goroutine。

并发编程模型:Go 语言提供了 channel 和 select 语句,使得在 goroutine 之间进行通信和同步变得非常简单。这是一种不同于传统的共享内存并发模型的并发编程模型,它更易于理解和使用。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/624899
推荐阅读
相关标签
  

闽ICP备14008679号