网关负责客户端的接入,因为时间原因都使用了websocket协议,目前只做到固定网关,也就是客户端直接连接指定网关。后面优化则会有一个网关发现服务,提供http接口返回目前最佳网关。
网关使用了 github.com/gorilla/websocket 提供的框架,主要负责处理客户端的连接,数据识别、转发数据。网关接受来自用户的数据并判断其类型,未登录用户不能发送非登录类型数据,确认正常数据后直接存进消息队列中。并且接受来自消息队列传来的信息,转发至对应客户端中。
接受来自客户端的数据:
func (self *WsServer) DealMsg(wsocket *Wsconn) {
defer func() {
wsocket.Stopchan <- 1
// 移除map
if wsocket.IsRegister() {
delete(self.Register, wsocket.GetId())
} else {
delete(self.UnRegister, wsocket.GetId())
}
// 将连接掉线信息 发送给UserControl服务
var data1 Data
data1.Type = LoseConnect
data1.Id = wsocket.GetId()
tr := transfer{From: GateName, FromType: GateWay, Data: data1, Id: wsocket.id}
var json = jsoniter.ConfigCompatibleWithStandardLibrary
data, err := json.Marshal(tr)
if err != nil {
fmt.Println("json err :%v", err)
return
}
// 将信息转发至消息队列 并加工
err = mq.Publish("DealServer", data)
if err != nil {
fmt.Println("RabbitMq:", err.Error())
}
}()
for {
msg, err := wsocket.Receive()
if err != nil {
// 判断是不是超时
if netErr, ok := err.(net.Error); ok {
if netErr.Timeout() {
fmt.Printf("ReadMessage timeout remote: %v\n", wsocket.conn.RemoteAddr())
return
}
}
// 其他错误,如果是 1001 和 1000 就不打印日志
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseNormalClosure) {
fmt.Printf("ReadMessage other remote:%v error: %v \n", wsocket.conn.RemoteAddr(), err)
return
}
fmt.Println(err.Error())
return
}
if len(msg) == 0 {
continue
}
// wsocket.Send([]byte("6666"))
var Type int64
Type, err = jsonparser.GetInt(msg, "type")
if err != nil {
fmt.Println("解析json", err)
// 错误解析 发送给客户端
data := Data{Type: ERROR, Data: []byte("数据解析出错")}
var json = jsoniter.ConfigCompatibleWithStandardLibrary
databyte, err := json.Marshal(&data)
if err != nil {
fmt.Println("json err :%v", err)
continue
}
wsocket.Send(databyte)
continue
}
// 心跳
if Type == Heat {
continue
}
fmt.Println("接受:" + wsocket.GetId() + string(msg))
if !wsocket.IsRegister() {
// 判断类型 如果用户没有注册则拒绝 否则发送至rabbitmq
if Type != Login && Type != Register && !wsocket.IsRegister() {
// 没有登陆成功 且发送不是登录也不是注册
data := Data{Type: ERROR, Data: []byte("请先登录")}
var json = jsoniter.ConfigCompatibleWithStandardLibrary
databyte, err := json.Marshal(&data)
if err != nil {
fmt.Println("json err :%v", err)
continue
}
wsocket.Send(databyte)
continue
}
}
var data1 Data
//var json1 = jsoniter.ConfigCompatibleWithStandardLibrary
err = json.Unmarshal(msg, &data1)
if err != nil {
fmt.Println("json error:", err)
return
}
tr := transfer{From: GateName, FromType: GateWay, Data: data1, Id: wsocket.GetId()}
var json = jsoniter.ConfigCompatibleWithStandardLibrary
data, err := json.Marshal(tr)
if err != nil {
fmt.Println("json err :%v", err)
continue
}
//fmt.Println("send")
// 将信息转发至消息队列 并加工
err = mq.Publish("DealServer", data)
if err != nil {
fmt.Println("RabbitMq:", err.Error())
}
}
}
接受来自消息队列的数据:
func (w *WsServer) DealRabbitmqMsg(delivery amqp.Delivery) {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
var transfer1 transfer
err := json.Unmarshal(delivery.Body, &transfer1)
if err != nil {
fmt.Println(err)
return
}
ID := transfer1.Id
Type := transfer1.Type
// 如果属于注册结果 查看注册结果
if Type == Login {
// err = json.Unmarshal(transfer1.Data, &data1)
// if err != nil {
// fmt.Println(err)
// return
// }
// fmt.Println((transfer1.Data))
var loginResult LoginResult
err := json.UnmarshalFromString(transfer1.Data.Data.(string), &loginResult)
if err != nil {
fmt.Println(err)
return
}
// if err := mapstructure.Decode(transfer1.Data.Data, &loginResult); err != nil {
// fmt.Println(err)
// return
// }
// 说明登录成功 记录
//fmt.Println(loginResult)
if loginResult.Result {
if w.UnRegister[ID] == nil {
fmt.Println(ID + "查询失败1")
return
}
w.UnRegister[ID].SetRegister(true)
w.UnRegister[ID].SetId(loginResult.UserId)
w.Register[loginResult.UserId] = w.UnRegister[ID]
delete(w.UnRegister, ID)
ID = loginResult.UserId
fmt.Println("登陆成功", w.Register[loginResult.UserId])
} else {
if w.UnRegister[ID] == nil {
fmt.Println(ID + "查询失败2")
return
}
// 发给未注册map
d, err := json.Marshal(transfer1.Data)
if err != nil {
fmt.Println(err)
return
}
w.UnRegister[ID].Send(d)
return
}
}
if w.Register[ID] == nil {
fmt.Println(ID + "查询失败3")
return
}
// fmt.Println("已注册")
// 将消息发送给指定socket 已注册
d, err := json.Marshal(transfer1.Data)
if err != nil {
fmt.Println(err)
return
}
// time.Sleep(time.Second)
fmt.Println("rabbitmq" + ID + string(d))
w.Register[ID].Send(d)
}