go websocket 测试案例

上次写完 websocket 服务端后,想着测试一下最大能承受多少连接,一试就试出来了bug

  • 先总结一下吧
    • 第一次:关闭管道后继续发送数据,,导致panic
    close(ch)
    ch<-data
    
    • 第二次:大量测试请求过来,因为一些坏连接而造成发送操作的阻塞

一个程序不断的发送信息

package main

import (
	"golang.org/x/net/websocket"
	"log"
	"strconv"
	"sync"
	"sync/atomic"
	"time"
)

var (
	origin = "https://baidu.com"
	url    = "wss://*"
	start  = make(chan struct{})
	// 计数
	done int32
	// 每个连接发送的信息数量 = msgNums + 1
	msgNums = 50
	wg      sync.WaitGroup
)

func Worker(id int) {
	ws, err := websocket.Dial(url, "", origin)
	if err != nil {
		log.Println("worker ", id, " dial fail:", err)
		return
	}

	// 等待开始
	<-start

	send := 0

	defer func() {
		ws.Close()
		log.Printf("worker %3d done, send:%3d \n", id, send)
		wg.Done()
	}()

	for {
		msg := []byte("{\"msg\":\"worker " + strconv.Itoa(id) + "\"}")
		_, err := ws.Write(msg)
		if err != nil {
			return
		}
		send++
		// 自定义数量
		if send > msgNums {
			// 结束全部任务
			atomic.AddInt32(&done, 1)
			return
		}

		time.Sleep(time.Second)
	}
}

func main() {
	// 建立连接
	for i := range [70][0]int{} {
		go Worker(i)
		wg.Add(1)
	}
	// 开始发送
	close(start)
	// 等待发送任务完成
	wg.Wait()
	// 打印完成结果
	log.Println("done:", done)

	// 发送结束信息,可能不会收到
	ws, err := websocket.Dial(url, "", origin)
	if err != nil {
		panic(err)
	}
	for range [5][0]int{} {
		msg := []byte("end")
		_, err := ws.Write(msg)
		if err != nil {
			panic(err)
		}
		time.Sleep(time.Millisecond * 500)
	}
}

另一个程序不断接收信息(只开启一个连接)

package main

import (
	"golang.org/x/net/websocket"
	"io/ioutil"
	"log"
	"sync"
)

// 只有一个连接,不处理 err,不关闭
func Read(ws *websocket.Conn) (data []byte, ok bool) {
	r, err := ws.NewFrameReader()
	if err != nil {
		return
	}
	fr, err := ws.HandleFrame(r)
	if err != nil {
		return
	}
	if fr == nil {
		return
	}
	data, err = ioutil.ReadAll(fr)
	if err != nil {
		return
	}
	return data, true
}

var (
	origin   = "https://baidu.com"
	url      = "wss://*"
	m        sync.Map
	msgNums  = 51
	readChan = make(chan string, 2000)
)

func Worker() {
	ws, err := websocket.Dial(url, "", origin)
	if err != nil {
		log.Println("worker dial fail:", err)
		return
	}

	exit := make(chan struct{})

	go func() {
		for {
			select {
			case s := <-readChan:
				value, ok := m.Load(s)
				if ok {
					m.Store(s, value.(int)+1)
				} else {
					m.Store(s, 1)
				}
			case <-exit:
				return
			}
		}
	}()

	for {
		data, ok := Read(ws)
		if ok {
			s := string(data)
			if s == "end" {
				close(exit)
				return
			}
			readChan <- s
		}
	}
}

func main() {
	defer func() {
		num := 0
		all := 0
		m.Range(func(key, value interface{}) bool {
			log.Printf("%20s : %3d", key, value)
			num++
			if value == msgNums {
				all++
			}
			return true
		})
		// 接收到的worker数量
		log.Println("total worker: ", num)
		// 全部接收数量
		log.Println("all recv num: ", all)
	}()
	Worker()
}

  • 最后,一般来说,只要连接建立,发送是没问题的,主要考虑的就是接收能力。
  • 在阿里的单核服务器上,瓶颈在网络上,卡的死死的,每个连接每秒发送一次的情况下,可以有70 个连接左右,具体参数调整后会有差异,但作为学习和平时使用,100以内的连接数是完全可以胜任的

你可能感兴趣的:(websocket,golang,websocket客户端)