**Summary of Changes** 1. Add an example that uses the write buffer pool The loop process of the websocket connection is inner the http handler at existing examples, This usage will cause the 8k buffer(4k read buffer + 4k write buffer) allocated by net.http can't be GC(Observed by heap profiling, see picture below) . The purpose of saving memory is not achieved even if the WriteBufferPool is used. In example bufferpool, server process websocket connection in a new goroutine, and the goroutine created by the net.http will exit, then the 8k buffer will be GC.  Co-authored-by: hakunaliu <hakunaliu@tencent.com> Co-authored-by: Corey Daley <cdaley@redhat.com>
90 lines
1.6 KiB
Go
90 lines
1.6 KiB
Go
//go:build ignore
|
|
// +build ignore
|
|
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"log"
|
|
"net/url"
|
|
"os"
|
|
"os/signal"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/gorilla/websocket"
|
|
)
|
|
|
|
var addr = flag.String("addr", "localhost:8080", "http service address")
|
|
|
|
func runNewConn(wg *sync.WaitGroup) {
|
|
defer wg.Done()
|
|
|
|
interrupt := make(chan os.Signal, 1)
|
|
signal.Notify(interrupt, os.Interrupt)
|
|
|
|
u := url.URL{Scheme: "ws", Host: *addr, Path: "/ws"}
|
|
log.Printf("connecting to %s", u.String())
|
|
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
|
|
if err != nil {
|
|
log.Fatal("dial:", err)
|
|
}
|
|
defer c.Close()
|
|
|
|
done := make(chan struct{})
|
|
|
|
go func() {
|
|
defer close(done)
|
|
for {
|
|
_, message, err := c.ReadMessage()
|
|
if err != nil {
|
|
log.Println("read:", err)
|
|
return
|
|
}
|
|
log.Printf("recv: %s", message)
|
|
}
|
|
}()
|
|
|
|
ticker := time.NewTicker(time.Minute * 5)
|
|
defer ticker.Stop()
|
|
|
|
for {
|
|
select {
|
|
case <-done:
|
|
return
|
|
case t := <-ticker.C:
|
|
err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
|
|
if err != nil {
|
|
log.Println("write:", err)
|
|
return
|
|
}
|
|
case <-interrupt:
|
|
log.Println("interrupt")
|
|
|
|
// Cleanly close the connection by sending a close message and then
|
|
// waiting (with timeout) for the server to close the connection.
|
|
err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
|
if err != nil {
|
|
log.Println("write close:", err)
|
|
return
|
|
}
|
|
select {
|
|
case <-done:
|
|
case <-time.After(time.Second):
|
|
}
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
log.SetFlags(0)
|
|
wg := &sync.WaitGroup{}
|
|
for i := 0; i < 1000; i++ {
|
|
wg.Add(1)
|
|
go runNewConn(wg)
|
|
}
|
|
wg.Wait()
|
|
}
|