服务器推送
概念
在传统 HTTP 请求中,一个 HTML 页面如果包含了其他图片、CSS 样式表等外部资源,需要发送多个请求(多轮请求耗时)。
服务器推送就是为了解决这样一种问题,服务器推送(server push)指的是,还没有收到浏览器的请求,服务器就把各种资源推送给浏览器。
比如,浏览器只请求了 index.html
,但是服务器把 index.html
、style.css
、example.png
全部发送给浏览器。这样的话,只需要一轮 HTTP 通信,浏览器就得到了全部资源,提高了性能。
对于服务器推送,有一个很麻烦的问题。所要推送的资源文件,如果浏览器已经有缓存,推送就是浪费带宽。即使推送的文件版本更新,浏览器也会优先使用本地缓存。
一种解决办法是,只对第一次访问的用户开启服务器推送。
Gin server push
http.Pusher 推送仅支持 **Go 1.8+**,Gin 中使用 c.Push()
获取 http.Pusher:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| func main() { r := gin.Default() r.Static("/assets", "./assets") r.SetHTMLTemplate(html)
r.GET("/", func(c *gin.Context) { if pusher := c.Writer.Pusher(); pusher != nil { if err := pusher.Push("/assets/app.js", nil); err != nil { log.Printf("Failed to push: %v", err) } } c.HTML(200, "https", gin.H{ "status": "success", }) })
r.RunTLS(":8080", "./testdata/server.pem", "./testdata/server.key") }
|
优雅的关闭服务器
http.Shutdown
在 Go 1.8 中,考虑使用 http 包自带的 Shutdown()
方法优雅的关闭服务器。该方法需要传入一个 Context 参数,当程序终止时其中不会中断活跃的连接,会等待活跃连接闲置或 Context 终止(手动 cancel 或超时)最后才终止程序
特别注意:
Gin 中使用 http.Shutdwon
在具体用应用中我们可以配合 signal.Notify 函数来监听系统退出信号,来完成程序优雅退出。
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
|
package main
import ( "context" "log" "net/http" "os" "os/signal" "time"
"github.com/gin-gonic/gin" )
func main() { router := gin.Default() router.GET("/", func(c *gin.Context) { time.Sleep(5 * time.Second) c.String(http.StatusOK, "Welcome Gin Server") })
srv := &http.Server{ Addr: ":8080", Handler: router, }
go func() { if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("listen: %s\n", err) } }()
quit := make(chan os.Signal) signal.Notify(quit, os.Interrupt) <-quit log.Println("Shutdown Server ...")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatal("Server Shutdown:", err) } log.Println("Server exiting") }
|