Golang 消息推送系统

  • 使用 websocket 协议,实现全局推送,和分房间推送,实现用户加入房间,退出房间

  • gateway 长连接网关服务器,管理全部的链接,以及房间等相关操作

  • logic 逻辑服务器 管理发送全局推送,单个房间推送,加入房间,离开房间等相关操作

  • 代码目录详情

├── gateway // 长连接网关服务器
│   ├── push_job.go    // 分发任务
│   ├── room.go        // 房间,可作为某一类型的推送管理中心
│   ├── room_manage.go // 房间管理
│   ├── ws_conn.go     // 简单封装的websocket方法
│   ├── ws_handle.go   // 处理websocket协议方法
│   └── ws_server.go   // websocket服务
├── logic  //逻辑服务器    
│   ├── http_handle.go // 推送,房间相关
│   └── http_server.go // http服务
└── main.go

websocket相关

  • 定义WsConnection结构体
type WsConnection struct {
	mu        sync.Mutex 
	connId    string            // 链接ID
	ws        *websocket.Conn   // ws链接
	readChan  chan *WSMessage   // 读取数据的管道
	writeChan chan *WSMessage   // 写数据的管道
	closeChan chan bool         // 关闭链接的管道
	isOpen    bool              // 链接是否有效
	addRoom   *sync.Map         // 该链接加入了那些房间
	clientIp  string            // 客户端IP
}
  • 维持心跳
switch {
   case msg.Type == 1://{"type":1,"data":"PING"},{"type":1,"data":"PONG"}
	_ = w.ws.SetReadDeadline(time.Now().Add(time.Second * 10))
	_ = w.SendMsg(&WSMessage{Type: 1, Data: "PONG"})
   default:
	fmt.Println("OTHER", msg.Type, msg.Data)
}

房间管理

//一个房间代表一个订阅推送类型
type Room struct {
	id    int       // 房间ID
	title string    // 房间标题
	RConn sync.Map  // 加入该房间的链接
}

type RoomManage struct {
	AllRoom sync.Map   // 所有的房间
	AllConn sync.Map   // 该网关的上的全部链接
}

gateway 协议 在线测试WS

  • ws://0.0.0.0:8888/connect

  • PING Client -> Server

{"type":1,"data":"PING"}
  • PONG Server -> Client
{"type":1,"data":"PONG"}

logic 协议

  • 全部推送
curl  http://0.0.0.0:9999/push/all -X POST -d "val=test push&tag=3"
  • 单个房间推送
curl  http://0.0.0.0:9999/push/room -X POST -d "val=test push&tag=3&id=1"
  • 加入房间 (wsId 在用户链接上gateway时可以得到)
curl http://0.0.0.0:9999/room/join -X POST -d "id=1&wsId=3cc97117-aa4d-55bb-86db-a1d77e51283b"
  • 离开房间
curl http://0.0.0.0:9999/room/leave -X POST -d "id=1&wsId=3cc97117-aa4d-55bb-86db-a1d77e51283b"

DEMO 代码地址

联系 QQ: 3355168235