Golang 游戲leaf系列(九) 官方issues摘錄

在查看官方issues時(shí)饰抒,也發(fā)現(xiàn)了一些個(gè)人覺(jué)得有用的討論,摘錄一下

一诀黍、issues 希望可以增強(qiáng)下log的功能

Q:leaf的log蠻好用的了袋坑,可以log到文本。但是現(xiàn)在需要做日志分析眯勾。要能支持json格式枣宫,異步log等等。希望可以加強(qiáng)下吃环。
看了下zap日志庫(kù)也颤,感覺(jué)過(guò)去復(fù)雜了。有沒(méi)有簡(jiǎn)單實(shí)用郁轻,能分析的日志庫(kù)翅娶?
A:Leaf 的 log 的定位并非用于數(shù)據(jù)分析,最好額外加一套用于數(shù)據(jù)分析的機(jī)制,同時(shí)也保留 Leaf 的 log故觅。

二厂庇、issues 服務(wù)端崩潰

zcwtop:請(qǐng)問(wèn)下,你是如何設(shè)計(jì)“一局游戲開(kāi)一個(gè)Goroutine”的输吏。能否給個(gè)簡(jiǎn)單的demo或者思路权旷。
我自己寫,一局游戲基本上是每個(gè)操作都放在goroutine里運(yùn)行的贯溅,用的是leaf的順序goroutine拄氯。這樣感覺(jué)goroutine會(huì)非常多,不知道這樣設(shè)計(jì)是不是錯(cuò)了它浅?

exfun:為什么每個(gè)操作都要單獨(dú)開(kāi)goroutine译柏。我之前就是開(kāi)太多了,幾十局游戲開(kāi)運(yùn)行完全跑不出問(wèn)題姐霍。跑幾萬(wàn)的次數(shù)就崩潰鄙麦,這就是我開(kāi)個(gè)issue求助的原因,找BUG找半天。我聽(tīng)了作者了。盡量少開(kāi)拖刃,一局游戲的邏輯操作都放一個(gè)goroutine里執(zhí)行,數(shù)據(jù)同步放到另外一個(gè)goroutine專門處理骂因,我們用的Postgress。這樣防止并發(fā)下未知的RACE赃泡。簡(jiǎn)單點(diǎn)好

zcwtop:是啊寒波。我現(xiàn)在感覺(jué)是太多了。我現(xiàn)在的設(shè)計(jì)是這樣的升熊,假如一局游戲的結(jié)構(gòu)是

type T struct {
    *g // leaf 平行的go
    ...
}

func (t *T) add {
    t.Go(func() {
        // ...
    }, func(){
        //...
    })
}

func (t *T) del {
    t.Go(func() {
        // ...
    }, func(){
        //...
    })
}

基本上每個(gè)操作都是這樣俄烁。如果改成一個(gè)go運(yùn)行,我該如何改级野? 或者你是如何寫的页屠,能否給個(gè)參考。

exfun:我沒(méi)有用leaf這個(gè)勺阐,用go 關(guān)鍵字聲明的。leaf的只用了它的消息和工具類這些矛双。我是一局游戲比如game *Game, 然后會(huì)在一個(gè)goroutinue里面執(zhí)行渊抽,比如 go game.Process() , 然后在process里面完成單局所有的事情议忽。游戲局完了之后懒闷,這個(gè)goroutine就會(huì)執(zhí)行完,等待GC回收。

zcwtop:那是不是這個(gè)Process是一個(gè)死循環(huán)愤估,用select多路復(fù)用等待通道消息帮辟,然后執(zhí)行。我理解是不是類似這樣處理:

func (g *Game) Process(...) {
    begin()
    //...

    for {
        select {
        case c:=<-通道1:
            handle1()
        case c := <-通道2:
            handle2()
        }
    }

    //...

    end()
}
func (g *Game)handle1() {
    //...
}
func (g *Game)handle2() {
    //...
}

exfun:寫好點(diǎn)應(yīng)該是這樣的玩焰,leaf負(fù)責(zé)消息轉(zhuǎn)發(fā)chan通知由驹,來(lái)了就處理,注意游戲結(jié)束條件昔园。別一直結(jié)束不了卡住蔓榄,這樣就會(huì)有問(wèn)題。超時(shí)的地方得處理默刚!我們是在線答題的游戲甥郑,比較簡(jiǎn)單。

zcwtop:人多的時(shí)候一定要注意別資源競(jìng)爭(zhēng)(多核下就很容易崩潰)荤西,要么用鎖澜搅,原子,條件變量控制邪锌∶闾桑或者用chan來(lái)傳遞消息。以下是我一個(gè)Game一個(gè)goroutine來(lái)控制游戲過(guò)程的流程Process() 秃流。重構(gòu)后的代碼赂蕴,比之前清晰多了,這也是我第一次寫golang舶胀,還需要學(xué)習(xí)的東西很多概说。

func (GR *GameRoom) Process() {
    // 處理游戲過(guò)程結(jié)束/正常/異常
    defer func() {
        GR.End()
        if e := recover(); e != nil {
            panic(e)
        }
    }()
    GR.Playing = true
    gameStartTime := conf.GameConfig.StartTime
    robotTime := conf.GameConfig.RobotTime
Playing:
    for {
        select {
        case m := <-GR.MsgChan:
            player := m.P
            switch m.Mtype {
            case MSG_JOIN:
                GR.onJoin(player)
            case MSG_ANSWER:
                GR.onAnswer(player, m.Answer, m.Pm)
            }
        case wf := <-GR.WaitChan:
            switch wf {
            case WAIT_GAME:
                // 游戲開(kāi)始倒計(jì)時(shí),補(bǔ)充一部分AI
                joinRobots(GR, utils.RandIntFrom2(18, 25))
                // 等待是否補(bǔ)充足房間
                time.AfterFunc(time.Second*time.Duration(robotTime), func() {
                    GR.WaitChan <- ON_RO_JOIN
                })
            case ON_RO_JOIN:
                // 不足AI
                joinRobots(GR, 0)
                // 剩余倒計(jì)時(shí)
                time.AfterFunc(time.Second*time.Duration(gameStartTime-robotTime), func() {
                    GR.WaitChan <- ON_GAME_START
                })
            case ON_GAME_START:
                // 游戲開(kāi)始
                GR.Start()
            case ON_RO_ANS_1:
                // 機(jī)器人第一次回答
                helpRobotAnswer(GR, true, false)
                time.AfterFunc(time.Second*time.Duration(1), func() {
                    GR.WaitChan <- ON_RO_ANS_2
                })
            case ON_RO_ANS_2:
                // 機(jī)器人第二次回答
                helpRobotAnswer(GR, false, false)
                time.AfterFunc(time.Second*time.Duration(1), func() {
                    GR.WaitChan <- ON_RO_ANS_3
                })
            case ON_RO_ANS_3:
                helpRobotAnswer(GR, false, true)
                // 倒計(jì)時(shí)回答結(jié)束
                time.AfterFunc(time.Second*time.Duration(GR.AnswerTimeout-4), func() {
                    GR.WaitChan <- ON_ANSWER_END
                })
            case ON_ANSWER_END: // 回答結(jié)束嚣伐,結(jié)算
                GR.onAnswerOver()
            case ON_SEND_QUESTION: // 出題
                GR.sendQuestion()
            case MSG_END_GAME: // 游戲結(jié)束
                //break game
                break Playing
                // goto END
            }
        }
    }
    //END:
    log.Debug("Game goroutine over ->%s", GR.Uuid)
}
三糖赔、Leaf 中如何做消息廣播

游戲服務(wù)器一定需要用戶管理,最常見(jiàn)的方式就是建立用戶 ID 到用戶實(shí)例的映射關(guān)系(還有可能存在用戶帳號(hào) ID轩端、用戶名到用戶實(shí)例的映射關(guān)系)放典。例如:

users = make(map[int]*User)

User 本身為了簡(jiǎn)單,可以直接組合 Agent:

type User struct {
    gate.Agent
}

這樣的話基茵,廣播消息就是:

for _, user := range users {
    user.WriteMsg(msg)
}

一個(gè)最簡(jiǎn)單的廣播的例子:打開(kāi) Leafserver game/internel/chanrpc.go 文件奋构,加入一個(gè)全局變量。

var agents = make(map[gate.Agent]struct{})
agents 的管理:

// agent 被創(chuàng)建時(shí)
func rpcNewAgent(args []interface{}) {
    a := args[0].(gate.Agent)
    agents[a] = struct{}{}
}

// agent 被關(guān)閉時(shí)
func rpcCloseAgent(args []interface{}) {
    a := args[0].(gate.Agent)
    delete(agents, a)
}
由此可見(jiàn) agents 中保存了當(dāng)前所有連接拱层,廣播的處理:

for a := range agents {
    a.WriteMsg(msg)
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末弥臼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子根灯,更是在濱河造成了極大的恐慌径缅,老刑警劉巖掺栅,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異纳猪,居然都是意外死亡氧卧,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門氏堤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)沙绝,“玉大人,你說(shuō)我怎么就攤上這事丽猬∷薇ィ” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵脚祟,是天一觀的道長(zhǎng)谬以。 經(jīng)常有香客問(wèn)我,道長(zhǎng)由桌,這世上最難降的妖魔是什么为黎? 我笑而不...
    開(kāi)封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮行您,結(jié)果婚禮上铭乾,老公的妹妹穿的比我還像新娘。我一直安慰自己娃循,他們只是感情好炕檩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著捌斧,像睡著了一般笛质。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捞蚂,一...
    開(kāi)封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天妇押,我揣著相機(jī)與錄音,去河邊找鬼姓迅。 笑死敲霍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的丁存。 我是一名探鬼主播肩杈,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼解寝!你這毒婦竟也來(lái)了扩然?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤编丘,失蹤者是張志新(化名)和其女友劉穎与学,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嘉抓,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡索守,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了抑片。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卵佛。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖敞斋,靈堂內(nèi)的尸體忽然破棺而出截汪,到底是詐尸還是另有隱情,我是刑警寧澤植捎,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布衙解,位于F島的核電站,受9級(jí)特大地震影響焰枢,放射性物質(zhì)發(fā)生泄漏蚓峦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一济锄、第九天 我趴在偏房一處隱蔽的房頂上張望暑椰。 院中可真熱鬧,春花似錦荐绝、人聲如沸一汽。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)召夹。三九已至,卻和暖如春委造,著一層夾襖步出監(jiān)牢的瞬間戳鹅,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工昏兆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枫虏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓爬虱,卻偏偏與公主長(zhǎng)得像隶债,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子跑筝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容