亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁(yè) > 編程 > Golang > 正文

剖析Go編寫的Socket服務(wù)器模塊解耦及基礎(chǔ)模塊的設(shè)計(jì)

2020-04-01 19:11:52
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
這篇文章主要介紹了Go的Socket服務(wù)器模塊解耦及日志和定時(shí)任務(wù)的模塊設(shè)計(jì),舉了一些Go語(yǔ)言編寫的服務(wù)器模塊的例子,需要的朋友可以參考下
 

Server的解耦—通過Router+Controller實(shí)現(xiàn)邏輯分發(fā)

在實(shí)際的系統(tǒng)項(xiàng)目工程中中,我們?cè)趯懘a的時(shí)候要盡量避免不必要的耦合,否則你以后在更新和維護(hù)代碼的時(shí)候會(huì)發(fā)現(xiàn)如同深陷泥潭,隨便改點(diǎn)東西整個(gè)系統(tǒng)都要變動(dòng)的酸爽會(huì)讓你深切后悔自己當(dāng)初為什么非要把東西都寫到一塊去(我不會(huì)說我剛實(shí)習(xí)的時(shí)候就是這么干的。。。)
所以這一篇主要說說如何設(shè)計(jì)Sever的內(nèi)部邏輯,將Server處理Client發(fā)送信息的這部分邏輯與Sevrer處理Socket連接的邏輯進(jìn)行解耦~
這一塊的實(shí)現(xiàn)靈感主要是在讀一個(gè)HTTP開源框架: Beego  的源代碼的時(shí)候產(chǎn)生的,Beego的整個(gè)架構(gòu)就是高度解耦的,這里引用一下作者的介紹:
beego 是基于八大獨(dú)立的模塊構(gòu)建的,是一個(gè)高度解耦的框架。當(dāng)初設(shè)計(jì) beego 的時(shí)候就是考慮功能模塊化,用戶即使不使用 beego 的 HTTP 邏輯,也依舊可以使用這些獨(dú)立模塊,例如:你可以使用 cache 模塊來(lái)做你的緩存邏輯;使用日志模塊來(lái)記錄你的操作信息;使用 config 模塊來(lái)解析你各種格式的文件。所以 beego 不僅可以用于 HTTP 類的應(yīng)用開發(fā),在你的 socket 游戲開發(fā)中也是很有用的模塊,這也是 beego 為什么受歡迎的一個(gè)原因。大家如果玩過樂高的話,應(yīng)該知道很多高級(jí)的東西都是一塊一塊的積木搭建出來(lái)的,而設(shè)計(jì) beego 的時(shí)候,這些模塊就是積木,高級(jí)機(jī)器人就是 beego。  
這里上一張Beego的架構(gòu)圖:

Go,Socket

  這是一個(gè)典型的MVC框架,可以看到,當(dāng)用戶發(fā)送請(qǐng)求到beego后,Beego內(nèi)部在通過路由進(jìn)行參數(shù)的過濾,然后路由根據(jù)用戶發(fā)來(lái)的參數(shù)判斷調(diào)用哪個(gè)Controller執(zhí)行相關(guān)的邏輯,并在controller里調(diào)用相關(guān)的模塊實(shí)現(xiàn)功能。通過這種方式,Beego成功的將所有模塊都獨(dú)立出來(lái),也就是astaxie所說的“樂高積木化”。
       在這里,我們可以仿照Beego的架構(gòu),在Server內(nèi)部加入一層Router,通過Router對(duì)通過Socket發(fā)來(lái)的信息進(jìn)通過我們?cè)O(shè)定的規(guī)則行的判斷后,調(diào)用相關(guān)的Controller進(jìn)行任務(wù)的分發(fā)處理。在這個(gè)過程中不僅Controller彼此獨(dú)立,匹配規(guī)則和Controller之間也是相互獨(dú)立的。
       下面給出Router的實(shí)現(xiàn)代碼,其中Msg的結(jié)構(gòu)對(duì)應(yīng)的是Json字符串,當(dāng)然考慮到實(shí)習(xí)公司現(xiàn)在也在用這個(gè),修改了一部分,不過核心思路是一樣的哦:

復(fù)制代碼代碼如下:

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,我們將匹配規(guī)則judge和對(duì)應(yīng)的controller封裝了進(jìn)去,然后在Server端負(fù)責(zé)接收socket發(fā)送信息的函數(shù)handleConnection那里再實(shí)現(xiàn)Router內(nèi)部的遍歷即可:
復(fù)制代碼代碼如下:

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每次發(fā)來(lái)信息,我們就可以讓Router自動(dòng)跟現(xiàn)有的規(guī)則進(jìn)行匹配,最后調(diào)用對(duì)應(yīng)的Controller進(jìn)行邏輯的實(shí)現(xiàn)啦,下面給出一個(gè)controller的編寫實(shí)例,這個(gè)Controll的作用是發(fā)來(lái)的json類型是mirror的時(shí)候,將Client發(fā)來(lái)的信息原樣返回:
復(fù)制代碼代碼如下:

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)  

日志模塊的設(shè)計(jì)與定時(shí)任務(wù)模塊模塊
作為一個(gè)Server,日志(Log)功能是必不可少的,一個(gè)設(shè)計(jì)良好的日志模塊,不論是開發(fā)Server時(shí)的調(diào)試,還是運(yùn)行時(shí)候的維護(hù),都是非常有幫助的。
因?yàn)檫@里寫的是一個(gè)比較簡(jiǎn)化的Server框架,因此我選擇對(duì)Golang本身的log庫(kù)進(jìn)行擴(kuò)充,從而實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Log模塊。
在這里,我將日志的等級(jí)大致分為Debug,Operating,Error 3個(gè)等級(jí),Debug主要用于存放調(diào)試階段的日志信息,Operateing用于保存Server日常運(yùn)行時(shí)產(chǎn)生的信息,Error則是保存報(bào)錯(cuò)信息。
模塊代碼如下:
復(fù)制代碼代碼如下:

func LogErr(v ...interface{}) {  
  
    logfile := os.Stdout  
    log.Println(v...)  
    logger := log.New(logfile,"/r/n",log.Llongfile|log.Ldate|log.Ltime);  
    logger.SetPrefix("[Error]")  
    logger.Println(v...)  
    defer logfile.Close();  
}  
  
func Log(v ...interface{}) {  
  
    logfile := os.Stdout  
    log.Println(v...)  
    logger := log.New(logfile,"/r/n",log.Ldate|log.Ltime);  
    logger.SetPrefix("[Info]")  
    logger.Println(v...)  
    defer logfile.Close();  
}  
  
func LogDebug(v ...interface{}) {  
    logfile := os.Stdout  
    log.Println(v...)  
    logger := log.New(logfile,"/r/n",log.Ldate|log.Ltime);  
    logger.SetPrefix("[Debug]")  
    logger.Println(v...)  
    defer logfile.Close();  
}  
  
func CheckError(err error) {  
    if err != nil {  
        LogErr(os.Stderr, "Fatal error: %s", err.Error())  
    }  
}  

注意這里log的輸出我使用的是stdout,因?yàn)檫@樣在Server運(yùn)行的時(shí)候可以直接將log重定向到指定的位置,方便整個(gè)Server的部署。不過在日常開發(fā)的時(shí)候,為了方便調(diào)試代碼,我推薦將log輸出到指定文件位置下,這樣在調(diào)試的時(shí)候會(huì)方便很多(主要是因?yàn)間olang的調(diào)試實(shí)在太麻煩,很多時(shí)候都要依靠打log的時(shí)候進(jìn)行步進(jìn)。便于調(diào)試的Log模塊代碼示意:
復(fù)制代碼代碼如下:

func Log(v ...interface{}) {  
  
    logfile := os.OpenFile("server.log",os.O_RDWR|os.O_APPEND|os.O_CREATE,0);  
    if err != nil {  
        fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())  
        return    }  
    log.Println(v...)  
    logger := log.New(logfile,"/r/n",log.Ldate|log.Ltime);  
    logger.SetPrefix("[Info]")  
    logger.Println(v...)  
    defer logfile.Close();  
}  

然后就是計(jì)時(shí)循環(huán)模塊啦,日常運(yùn)行中,Server經(jīng)常要執(zhí)行一些定時(shí)任務(wù),比如隔一定時(shí)間刷新后臺(tái),隔一段時(shí)間自動(dòng)刷新爬蟲等等,在這里我設(shè)計(jì)了一個(gè)Task接口,通過類似于TaskList的的方式將所有定時(shí)任務(wù)注冊(cè)后統(tǒng)一執(zhí)行,代碼如下:
復(fù)制代碼代碼如下:

type DoTask interface {  
    Excute()  
}  
  
var tasklist []interface{}  
  
func AddTask(controller DoTask) {  
    var arr interface{}  
    arr = controller  
    tasklist = append(tasklist,arr)  
    fmt.Println(tasklist)  
    }  

在這里以一個(gè)定時(shí)報(bào)時(shí)任務(wù)作為例子:
復(fù)制代碼代碼如下:

type Task1 struct {}  
  
func (this * Task1)Excute() {  
    timer := time.NewTicker(2 * time.Second)  
    for {  
        select {  
        case <-timer.C:  
            go func() {  
                Log(time.Now())  
            }()  
        }  
    }  
}  
  
func init() {  
    var task1 Task1  
    tasklist = make([]interface{} ,0 , 20)  
    AddTask(&task1)  
        for _, v := range tasklist {  
            v.(DoTask).Excute()  
        }  
  
}  

注意這里的定時(shí)任務(wù)要做成非阻塞的,否則整個(gè)Server都會(huì)卡在tasklist的第一個(gè)task的。。。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
蜜桃成人365av| 国产成人精品久久亚洲高清不卡| 在线免费黄网| 国产精品宾馆| 国产91对白刺激露脸在线观看| 成人黄色免费短视频| 国产日韩欧美在线看| 五月综合色婷婷| 久久久亚洲精华液精华液精华液| 精品久久一区二区三区| 人妻少妇精品无码专区久久| 午夜日韩成人影院| 久久久久九九视频| 免费在线不卡视频| 5278欧美一区二区三区| 欧美自拍偷拍一区二区| 91视频免费网址| 一区二区三区四区精品在线视频| 欧美激情一区二区视频| 成人福利片网站| 欧美激情精品久久久久久大尺度| 日韩成人xxxx| 一二三av在线| 青青草综合网| 国产精伦一区二区三区| 国产美女视频免费| 亚洲一级二级在线| 亚洲毛片aa| 国产精品久久精品国产| 在线观看一二三区| 久久精品欧美一区二区三区不卡| 希岛爱理一区二区三区av高清| 精品一区二区三区日本| 日韩欧美亚洲国产| 男人的天堂久久精品| 黄色网址网站在线观看| 国产aⅴ精品一区二区三区色成熟| 国产精品亚洲а∨天堂免在线| 北条麻妃在线观看视频| 国产美女在线观看| 成人激情小说网站| 亚洲第一第二区| 欧美色国产精品| 免费看欧美黑人毛片| 99视频在线免费| www成人免费观看网站| 成年网站免费视频黄| 欧美三级黄美女| 美女喷白浆视频| 中文字幕日韩av电影| 毛片在线能看| 日韩一区二区电影在线| 丁香亚洲综合激情啪啪综合| 欧美久久久影院| 国产精品裸体一区二区三区| 大吊一区二区三区| 成人黄色网页| 91九色论坛| 亚洲aⅴ日韩av电影在线观看| 成人免费在线视频播放| 国外成人免费在线播放| 亚洲AV无码成人片在线观看| 中文字幕免费精品一区高清| 国产精品99蜜臀久久不卡二区| 自拍偷拍精品视频| 国产欧美精品在线观看| 久草在线资源网| 国产日韩精品综合网站| 国产精品原创视频| 美女在线视频一区二区| 无码粉嫩虎白一线天在线观看| 国产精品一二三在线观看| 国产免费成人在线| 国产精品久久久久久影院8一贰佰| 国产情侣小视频| 亚洲二区在线观看| 精品一区二区三区四区五区| 国产精品第56页| 国产a精品视频| 国产九九在线| 亚洲精品高清视频在线观看| 一个人看的日本www的免费视频| 伊人婷婷久久| 日韩电影免费| 欧美最猛性xxxxx(亚洲精品)| www.狠狠操| 亚洲中文字幕无码av| 国产福利在线| 国产婷婷精品| 久久99久久99| 亚洲电影第三页| 在线观看黄色网| 亚洲五月激情网| 在线 丝袜 欧美 日韩 制服| 女人高潮特级毛片| 99精品中文字幕| 国产成人在线观看| 久久综合九色综合久久久精品综合| 久久免费手机视频| 热门国产精品亚洲第一区在线| 国产亚洲在线观看| 成人国产亚洲精品a区天堂华泰| 人妻一区二区三区四区| 欲香欲色天天天综合和网| 国产欧美一区二区三区在线| 91欧美精品| 国产精品s色| 欧美性xxxxxbbbbbb精品| 欧美三级电影网站| 法国伦理少妇愉情| 手机看片福利在线| www.99re7.com| 印度午夜性春猛xxx交| 亚洲成人激情在线| 国内精品久久久久久久影视麻豆| 欧美精品99久久久| 欧美激情福利视频在线观看免费| 你懂的在线视频观看| 亚洲第一综合天堂另类专| 亚洲精品一级| 韩国av网站在线| 中文字幕在线视频第一页| 三上悠亚在线免费观看| 久久久久久亚洲精品杨幂换脸| 91久久久久久| 精品国偷自产在线视频99| 97超碰人人模人人人爽人人爱| 国产欧美在线一区| 亚洲午夜久久久久| 高清不卡在线观看| 成人激情综合网| 天堂在线www天堂中文在线| 亚洲天堂中文字幕| 天天操综合520| 国产精品久久中文| 不卡一区视频| 亚洲精品成人图区| 亚洲国产精品一区二区久久恐怖片| 农村妇女精品一二区| 黄色大片免费看| 日韩经典一区二区| 成人激情电影一区二区| 91久久久久久久一区二区| 男人的天堂日韩| 日本一区二区成人| 欧美一区二区三区色| 午夜欧美一区二区三区免费观看| 97视频中文字幕| 在线观看国产小视频| 国产精品久久不卡| 69堂成人精品视频免费| 91玉足脚交嫩脚丫在线播放| 99热久久这里只有精品| 日韩成人免费av| 肉色超薄丝袜脚交69xx图片| 亚洲一区www| 亚洲另类图片另类电影| 国产精品自在线| 国产精品九九九九九九| 爽爽影院免费观看视频| www.精品久久| 欧美激情视频在线| 92看片淫黄大片欧美看国产片| 日韩少妇内射免费播放18禁裸乳| 91国内在线视频| 日韩有码第一页| 日韩免费特黄一二三区| 欧美人一级淫片a免费播放| av在线播放一区二区三区| 亚洲成人第一区| 日本一区二区在线免费观看| 免费在线色视频| 91久久国产综合久久蜜月精品| 九九视频精品全部免费播放| 久久亚洲AV成人无码国产野外| 中国黄色片视频| 精品无人区一区二区| av女优在线播放| 亚洲柠檬福利资源导航| 亚洲老妇xxxxxx| 日本电影全部在线观看网站视频| 美女被草91| 欧美羞羞免费网站| 欧美性在线观看| 日韩欧美国产精品综合嫩v| 中文字幕一区二区三区乱码图片| 怡红院一区二区| 亚洲欧美网站在线观看| 亚洲自拍欧美另类| 日韩av资源站| 你懂得在线网址| 欧洲国产伦久久久久久久| 波多野结衣一本| 日韩欧美一级在线| 成人在线一区二区三区| 亚洲一级视频在线观看| 一级片在线观看免费| 亚洲欧美日韩精品在线| 日韩视频免费中文字幕| 天天天天天天操| 国产69精品久久久久9999apgf| 北条麻妃在线一区二区免费播放| 黄网在线免费看| 手机福利小视频在线播放| 国产成人在线视频播放| 亚洲欧美视频在线播放| 欧美一级片免费在线| 99热这里只有成人精品国产| 在线免费观看日本欧美| 国产成人久久精品一区二区三区| 欧美超碰在线观看| igao视频网在线视频| 午夜小视频免费| h在线观看视频| 精品人妻一区二区三| 毛茸茸多毛bbb毛多视频| 亚洲性生活网站| 色噜噜狠狠色综合中国| 猛性xxxxx| 亚洲一区 二区| 国产免费看av| 国产成人高清激情视频在线观看| 夜夜嗨av一区二区三区网站四季av| 蜜桃av成人| 爆操妹子视频在线观看| 日本天码aⅴ片在线电影网站| 欧美在线导航| 成人毛片网站| 天堂av手机在线| 欧美色涩在线第一页| 专区另类欧美日韩| 欧美一区二区福利| 中文字幕乱码人妻无码久久| 精品动漫一区二区| 成年网站在线| 欧美国产第二页| 久久久国产精品一区| 免费高清成人在线| 日韩欧美国产小视频| 亚洲另类在线制服丝袜| 日韩久久精品网| 日韩视频免费大全中文字幕| 蜜桃色一区二区三区| 欧美系列一区二区| 超碰在线97观看| 欧美另类videoxo高潮| 亚洲天堂一区二区三区| 欧美日本韩国一区二区三区视频| 欧美亚韩一区二区三区| 亚洲国产高清在线观看视频| 亚洲午夜精品一区二区三区| 五月天天在线| 激情国产一区| 人人妻人人添人人爽欧美一区| 精品久久久久久久一区二区蜜臀| 精品人妻无码一区二区性色| 富二代精品短视频| 最近中文字幕在线6| 中文国产一区| 日本一不卡视频| 久久久久国产精品一区| 美日韩精品免费观看视频| 国产成年人视频网站| 日本大香伊一区二区三区| 日韩在线一区二区| 日本网站在线免费观看| 国内精品久久久久久久97牛牛| 国产成人l区| 精品国自产在线观看| 午夜精品久久久久久久四虎美女版| 少妇精品视频在线观看| 精品成人av| 天堂av在线资源| 日本一区二区三区久久久久久久久不| 99热这里只有精品首页| 亚洲国产精品久久久久婷婷老年| 北条麻妃一区二区三区在线| 日本一区二区三区免费看| 精品无人区卡一卡二卡三乱码免费卡| 精品中文字幕视频| 97国产在线| 热99re久久精品精品免费| 91久久精品一区| 日本高清不卡一区二区三区视频| 亚洲精品国产一区黑色丝袜| 一本色道精品久久一区二区三区| 高清视频一区二区三区四区| 欧美视频观看一区| 国产欧美一区二区精品仙草咪| 亚洲精品成a人在线观看| 爽爽爽在线观看| av网站免费大全| 欧美日韩三级| 国内精品免费在线观看| 91香蕉视频污在线观看| 欧美中文在线免费| 狠狠人妻久久久久久| 艳母动漫在线免费观看| 国产精品推荐精品| 五十路六十路七十路熟婆| 中文子幕无线码一区tr| 四虎影院在线域名免费观看| 亚洲国产aⅴ精品| eeuss影院www在线观看免费| 国产盗摄精品一区二区三区在线| 中文字幕在线观看高清| 亚洲av无码乱码国产精品| 日本黄色免费| aaaaa毛片| 免费在线高清av| 黄色免费在线观看网站| 久久一级大片| 国产视频在线视频| 国产成人aa精品一区在线播放| 丰满岳乱妇一区二区三区| 国产欧美日韩精品a在线观看| 久久99久久人婷婷精品综合| 亚洲精品日产| 日韩在线精品| 日韩精品一区二区三区中文不卡| 国产一二三四在线| 国产精品亚洲专一区二区三区| 欧美日韩一区中文字幕| 日本少妇全体裸体洗澡| 自拍偷在线精品自拍偷无码专区| 99免费视频| 自拍视频一区| 久久福利视频网|