網關負責客戶端的接入,因爲時間原因都使用了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)
}