[Golang] 從零開始寫Socket Server(5):Server的解耦—通過Router+Controller實現邏輯分發

       在實際的系統項目工程中中,我們在寫代碼的時候要儘量避免不必要的耦合,否則你以後在更新和維護代碼的時候會發現如同深陷泥潭,隨便改點東西整個系統都要變動的酸爽會讓你深切後悔自己當初爲什麼非要把東西都寫到一塊去(我不會說我剛實習的時候就是這麼幹的。。。)

       所以這一篇主要說說如何設計Sever的內部邏輯,將Server處理Client發送信息的這部分邏輯與Sevrer處理Socket連接的邏輯進行解耦~

       這一塊的實現靈感主要是在讀一個HTTP開源框架: Beego  的源代碼的時候產生的,Beego的整個架構就是高度解耦的,這裏引用一下作者的介紹:

    beego 是基於八大獨立的模塊構建的,是一個高度解耦的框架。當初設計 beego 的時候就是考慮功能模塊化,用戶即使不使用 beego 的 HTTP 邏輯,也依舊可以使用這些獨立模塊,例如:你可以使用 cache 模塊來做你的緩存邏輯;使用日誌模塊來記錄你的操作信息;使用 config 模塊來解析你各種格式的文件。所以 beego 不僅可以用於 HTTP 類的應用開發,在你的 socket 遊戲開發中也是很有用的模塊,這也是 beego 爲什麼受歡迎的一個原因。大家如果玩過樂高的話,應該知道很多高級的東西都是一塊一塊的積木搭建出來的,而設計 beego 的時候,這些模塊就是積木,高級機器人就是 beego。


       這裏上一張Beego的架構圖:


     

       這是一個典型的MVC框架,可以看到,當用戶發送請求到beego後,Beego內部在通過路由進行參數的過濾,然後路由根據用戶發來的參數判斷調用哪個Controller執行相關的邏輯,並在controller裏調用相關的模塊實現功能。通過這種方式,Beego成功的將所有模塊都獨立出來,也就是astaxie所說的“樂高積木化”。

       在這裏,我們可以仿照Beego的架構,在Server內部加入一層Router,通過Router對通過Socket發來的信息通過我們設定的規則進行判斷後,調用相關的Controller進行任務的分發處理。在這個過程中不僅Controller彼此獨立,匹配規則和Controller之間也是相互獨立的。

       下面給出Router的實現代碼,其中Msg的結構對應的是Json字符串,當然考慮到實習公司現在也在用這個,修改了一部分,不過核心思路是一樣的哦:

import (
	"utils"
	"fmt"
	"encoding/json"
)

type Msg struct {
	Conditions   map[string]interface{} `json:"meta"`
	Content interface{}            `json:"content"`
}

type Controller interface {
	Excute(message Msg) []byte
}

var routers [][2]interface{}

func Route(judge interface{} ,controller Controller) {
	switch judge.(type) {
	case func(entry Msg)bool:{
		var arr [2]interface{}
		arr[0] = judge
		arr[1] = controller
		routers = append(routers,arr)
	}
	case map[string]interface{}:{
		defaultJudge:= func(entry Msg)bool{
			for keyjudge , valjudge := range judge.(map[string]interface{}){
				val, ok := entry.Meta[keyjudge]
				if !ok {
					return false
				}
				if val != valjudge {
					return false
				}
			}
			return true
		}
		var arr [2]interface{}
		arr[0] = defaultjudge
		arr[1] = controller
		routers = append(routers,arr)
		fmt.Println(routers)
		}
	default:
		fmt.Println("Something is wrong in Router")
	}
}

      通過自定義接口Router,我們將匹配規則judge和對應的controller封裝了進去,然後在Server端負責接收socket發送信息的函數handleConnection那裏再實現Router內部的遍歷即可:

for _ ,v := range routers{
		pred := v[0]
		act := v[1]
		var message Msg
		err := json.Unmarshal(postdata,&message)
		if err != nil {
			Log(err)
		}
		if pred.(func(entry Msg)bool)(message) {
			result := act.(Controller).Excute(message)
			conn.Write(result)
			return
		}
	}

       這樣Client每次發來信息,我們就可以讓Router自動跟現有的規則進行匹配,最後調用對應的Controller進行邏輯的實現啦,下面給出一個controller的編寫實例,這個Controll的作用是發來的json類型是mirror的時候,將Client發來的信息原樣返回:

type MirrorController struct  {

}

func (this *MirrorController) Excute(message Msg)[]byte {
	mirrormsg,err :=json.Marshal(message)
	CheckError(err)
	return mirrormsg
}


func init() {
	var mirror 
	routers = make([][2]interface{} ,0 , 20)
	Route(func(entry Msg)bool{
		if entry.Meta["msgtype"]=="mirror"{
		return true}
		return  false
	},&mirror)
}

我已經把SocketServer系列的代碼整合到了一起,發佈到了我個人的github上:點擊鏈接, 希望大家有興趣的可以學習star一下~

    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章