Опишите проблему, с которой вы столкнулись
Я использую golang.org/x/net/websocket для трансляции около 100 сообщений в секунду, это не проблема, клиент может получать все сообщения, но когда я использую gorilla websocket, получаю только менее 10 сообщений, тогда websocket clientv будет поврежден .
…
Версии
Версия go: версия go go1.13.11 linux / amd64
версия пакета: c3dd95aea9779669bb3daafbd84ee0530c8ce1c1
…
"Покажи мне код!"
основной пакет
Импортировать (
"кодировка / json"
"github.com/gorilla/websocket"
"бревно"
"net / http"
"время"
)
const (
// Время, разрешенное для написания сообщения партнеру.
writeWait = 10 * время. секунда
// Time allowed to read the next pong message from the peer.
pongWait = 60 * time.Second
// Send pings to peer with this period. Must be less than pongWait.
pingPeriod = (pongWait * 9) / 10
// Maximum message size allowed from peer.
maxMessageSize = 512
)
var upgradeder = websocket.Upgrader {
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func (r * http.Request) bool {return true},
}
var newline = [] байт {'\ n'}
type Client struct {
концентратор * концентратор
conn * websocket.Conn
отправить сообщение чана
увидеть строку
}
type Hub struct {
карта клиентов [* Client] bool
широковещательный канал сообщение
зарегистрировать чан * Клиент
unregister chan * Client
}
func newHub () Hub {return & Hub {трансляция: make (chan msg),регистрация: make (chan * Client),unregister: make (chan * Client),клиенты: make (map [ Client] bool),
}
}
func (h * Hub) run () {
для {
Выбрать {
case client: = <-h.register:
h.clients [клиент] = истина
case client: = <-h.unregister:
если _, ок: = h.clients [клиент]; ОК {
удалить (h.clients, client)
закрыть (client.send)
}
case message: = <-h.broadcast:
для клиента: = диапазон h.clients {
if client.see == message.LogName {
client.send <- сообщение
}
//Выбрать {
// case client.send <- сообщение:
//По умолчанию:
// закрыть (client.send)
// удалить (h.clients, client)
//}
}
}
}
}
func (c * Client) readPump () {
defer func () {
c.hub.unregister <- c
_ = c.conn.Close ()
} ()
c.conn.SetReadLimit (maxMessageSize)
_ = c.conn.SetReadDeadline (time.Now (). Add (pongWait))
c.conn.SetPongHandler (func (string) error {_ = c.conn.SetReadDeadline (time.Now (). Add (pongWait)); return nil})
для {
_, сообщение, ошибка: = c.conn.ReadMessage ()
if err! = nil {
если websocket.IsUnexpectedCloseError (err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
ErrorLogger.Printf ("readPump завершился с ошибкой:% v", err)
}
перерыв
}
type recv struct {
LogName string `json:"logName"`
}
var rcv = &recv{}
if err := json.Unmarshal(message, &rcv); err != nil {
c.hub.unregister <- c
ErrorLogger.Printf("%s",err)
break
}
c.see = rcv.LogName
}
}
func (c * Client) writePump () {
тикер: = время.NewTicker (pingPeriod)
defer func () {
ticker.Stop ()
_ = c.conn.Close ()
} ()
для {
Выбрать {
case сообщение, ok: = <-c.send:
_ = c.conn.SetWriteDeadline (time.Now (). Add (writeWait))
if! ok {
// Хаб закрыл канал.
_ = c.conn.WriteMessage (websocket.CloseMessage, [] байт {})
возвращаться
}
w, err := c.conn.NextWriter(websocket.TextMessage)
if err != nil {
return
}
msgByte, _ := json.Marshal(message)
_, _ = w.Write(msgByte)
// Add queued chat messages to the current websocket message.
n := len(c.send)
_, _ = w.Write(newline)
for i := 0; i < n; i++ {
for msg := range c.send {
msgByte, _ := json.Marshal(msg)
_, err := w.Write(msgByte)
if err != nil {
newHub().unregister <- c
ErrorLogger.Printf("%s", err)
break
}
}
}
if err := w.Close(); err != nil {
return
}
case <-ticker.C:
_ = c.conn.SetWriteDeadline(time.Now().Add(writeWait))
if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil {
return
}
}
}
}
// serveWs обрабатывает запросы веб-сокетов от однорангового узла.
func serveWs (hub * Hub, w http.ResponseWriter, r * http.Request) {
conn, err: = upgradeder.Upgrade (w, r, nil)
if err! = nil {
log.Fatal (ошибка)
возвращаться
}
client: = & Client {hub: hub, conn: conn, send: make (chan msg, 1)}
client.hub.register <- клиент
// Allow collection of memory referenced by the caller by doing all work in
// new goroutines.
go client.writePump()
go client.readPump()
}
Ваш клиент написан для обработки нескольких документов JSON в одном сообщении WebSocket?
Покажите код с x / net / websocket, который работал.
Ваш клиент написан для обработки нескольких документов JSON в одном сообщении WebSocket?
Покажите код с x / net / websocket, который работал.
нет
основной пакет
Импортировать (
"кодировка / json"
"golang.org/x/net/websocket"
"io"
)
// веб-сокет 客户 端
type client struct {
строка идентификатора
сокет * websocket.Conn
отправить сообщение чана
увидеть строку
}
// 客户 端 管理
type clientManager struct {
карта клиентов [* клиент] bool
широковещательный канал сообщение
зарегистрировать чан * клиент
отменить регистрацию клиента chan *
}
var manager = clientManager {
трансляция: make (chan msg),
регистрация: make ( клиент чан
}
func (manager * clientManager) start () {
defer func () {
если ошибка: = восстановление (); err! = nil {
ErrorLogger.Printf ("паника при запуске () менеджера")
}
} ()
for {
select {
case conn := <-manager.register:
manager.clients[conn] = true
case conn := <-manager.unregister:
if _, ok := manager.clients[conn]; ok {
close(conn.send)
_ = conn.socket.Close()
delete(manager.clients, conn)
}
case msg := <-manager.broadcast:
for conn := range manager.clients {
if conn.see == msg.LogName {
conn.send <- msg
}
}
}
}
}
func (c * client) write () {
for msg := range c.send {
msgByte, _ := json.Marshal(msg) // 忽略错误
_, err := c.socket.Write(msgByte)
if err != nil {
manager.unregister <- c
ErrorLogger.Printf("%s",err)
break
}
}
}
func (c * client) read () {
для {
строка ответа var
если ошибка: = websocket.Message.Receive (c.socket, & reply); err! = nil {
if err! = io.EOF {
ErrorLogger.Printf ("% s", ошибка)
manager.unregister <- c
}
перерыв
}
type recv struct {
Строка LogName json:"logName"
}
var rcv = & recv {}
если ошибка: = json.Unmarshal ([] байт (ответ), & rcv); err! = nil {
manager.unregister <- c
ErrorLogger.Printf ("% s", ошибка)
перерыв
}
c.see = rcv.LogName
}
}
``
В пакете gorilla нет ограничения на широковещательное сообщение в секунду.
Если ваш клиент не предназначен для обработки нескольких документов JSON в сообщении WebSocket, удалите код, который записывает несколько документов в сообщение.
Ваш код x / net / websocket записывает один документ JSON для каждого сообщения WebSocket. Если вы сделаете то же самое с кодом гориллы, приложение, вероятно, будет работать должным образом.
удалите код, который записывает несколько документов в сообщение.
ты имел ввиду это?
// Add queued chat messages to the current websocket message.
n := len(c.send)
_, _ = w.Write(newline)
for i := 0; i < n; i++ {
for msg := range c.send {
msgByte, _ := json.Marshal(msg)
_, err := w.Write(msgByte)
if err != nil {
newHub().unregister <- c
ErrorLogger.Printf("%s", err)
break
}
}
}
Да, это ваш код, который добавляет несколько документов в сообщение веб-сокета.
Хорошо, у гориллы есть какая-нибудь переменная или API, которые могут заставить клиента получать больше сообщений за секунду?
Gorilla не имеет переменной или API, ограничивающего количество сообщений в секунду.
Код для упаковки нескольких документов JSON в одно сообщение WebSocket запустит затем отправку сообщений с очень высокой скоростью. Учитывая, что ваш клиент не предназначен для обработки нескольких документов JSON в одном сообщении WebSocket, вы можете ожидать, что ваше приложение потеряет сообщения при отправке сообщений с очень высокой скоростью.
Удалите код, процитированный парой комментариев, и проверьте снова.
Самый полезный комментарий
Gorilla не имеет переменной или API, ограничивающего количество сообщений в секунду.
Код для упаковки нескольких документов JSON в одно сообщение WebSocket запустит затем отправку сообщений с очень высокой скоростью. Учитывая, что ваш клиент не предназначен для обработки нескольких документов JSON в одном сообщении WebSocket, вы можете ожидать, что ваше приложение потеряет сообщения при отправке сообщений с очень высокой скоростью.
Удалите код, процитированный парой комментариев, и проверьте снова.