您好,登錄后才能下訂單哦!
這篇文章主要介紹“如何用GIN構建一個WEB服務”,在日常操作中,相信很多人在如何用GIN構建一個WEB服務問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何用GIN構建一個WEB服務”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
快速啟動一個 api
目錄
├── api \\ 服務入口 ├── cmd \\ 服務啟動入口 ├── config ├── doc └── chaper1.md├── go.mod ├── internal \\ 業務邏輯 ├── main.go ├── pkg \\ 三方包初始化 └── router \\ Api 路由
GIN && Cobra
一般 WEB 服務,都會包含多個模塊: API 接口、定時任務、消費 MQ 常駐進程等等,在這種情況下,很顯然直接使用 GIN 來啟動就只能開啟 API 模塊,十分不便。
我們用 Cobra 來管理項目的啟動,現在不用關心 Cobra 如何使用,現在要的是滿足我們需求。
很多時候人會陷入到細節里,就無法宏觀的把控全局設計。無論是做需求還是設計框架,都應該梳理整個流程,每個流程需要什么樣的技術,而技術細節反而不是最需要關心的。互聯網發展到今天,你遇到的問題一定有人遇到過要把關注點放到你的設計上。
初始化一個 rootCmd 來管理項目中所有的模塊
// main.go func main() { cmd.Execute()} // cmd/root.go var rootCmd = &cobra.Command{ Use: "提供WebApi服務", Short: "webApi",} func init() { rootCmd.AddCommand(apiCmd)} func Execute() { if err := rootCmd.Execute(); err != nil { fmt.Println("[錯誤]啟動失敗:", err) }} // cmd/api.go var httpServer *http.Server var apiCmd = &cobra.Command { Use: "api", Short: "apiCmd", Long: `apiCmd 提供api接口服務`, Run: func(cmd *cobra.Command, args []string) { address := fmt.Sprintf("%v:%v", "0.0.0.0", 8080) engine := gin.New() httpServer = &http.Server{ Addr: address, Handler: engine, IdleTimeout: time.Minute, } if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { fmt.Println("啟動失敗", err) }}, } }
這個時候啟動一下, 可以看到需要傳一個命令行參數:
? gin-web-layout git:(master) ? go run main.go webApi Usage: 提供WebApi服務 [command] Available Commands: api apiCmd completion Generate the autocompletion script for the specified shell help Help about any command
使用 go run main.go api
就可以啟動服務了
? gin-web-layout git:(master) ? go run main.go api [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. - using env: export GIN_MODE=release - using code: gin.SetMode(gin.ReleaseMode)
首先開始接入路由, 所見即所得,能快速的看到自己寫的成果
router/router.go func InitRouter(engine *gin.Engine) { engine.GET("/", func(c *gin.Context) { c.JSON(200, "ok") })} 在 cmd/api.go 增加以下代碼 engine := gin.New() router.InitRouter(engine)
這樣一個 hello world 就完成了,這個也是 gin 快速開始的內容。 啟動后訪問一下:
? gin-web-layout git:(master) ? curl http://0.0.0.0:8080 "ok"%
這個時候我們來完善一下啟動模塊的代碼,加上平滑重啟,設置 5 秒后退出
// cmd/api.go // 只展示核心代碼,完整代碼可以在 github 查看 // 等待 5 秒 timeout = 5 *time.sencond func OnServiceStop(timeout time.Duration) { quit := make(chan os.Signal) signal.Notify(quit, signals.Get()...) <-quit ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() err := httpServer.Shutdown(ctx) if err != nil { log.Fatalf("service stop error:%v", err) } log.Println("service is stopping") }
這樣就支持了熱啟動,然后就編譯啟動,ctrl+c, 他為什么沒阻塞 5 秒,直接就退出了?
因為 ctrl+c 的時候,會檢查是否有待處理的請求,如沒有就會直接退出。我們可以模擬一個耗時請求:
// router/router.go engine.GET("/", func(c *gin.Context) { time.Sleep(5 * time.Second) c.JSON(200, "ok") })
重新啟動后,再次 ctrl+c 會發現 5 秒后項目才退出完成。
題外話,線上的服務是如何發布部署的?
一般線上服務都會用網關調度流量,當我們一個服務接受到 kill(重啟腳本一般用 kill,殺掉 pid) 信號,就不再接受新請求。
這一點可以用我們剛配置的熱重啟驗證一下,把 timeout 設置 10s, 偽造一個耗時 10s 的請求,啟動后執行退出(用 ctrl+c 或者 kill, 本質都是發送一個信號), 然后再訪問服務,
會得到
? gin-web-layout git:(master) ? curl http://0.0.0.0:8080 curl: (7) Failed to connect to 0.0.0.0 port 8080: Connection refused
網關和服務會有心跳監測,無法提供服務后,網關自動踢掉服務,不再發流量,待恢復后再重新發流量。但是實際部署部署是另有方案,因為心跳是有間隔的,這個間隔期間服務退出了,就會造成大量的 502
實際線上操作為,當一臺服務要退出的時候,會先到網關摘流量,再執行平滑退出,啟動新服務,到網關掛上流量。 網關一般用的是阿里的 slb,也有人用 kong,都是一樣的套路。
到此,關于“如何用GIN構建一個WEB服務”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。