1. 程式人生 > >grpc-go與actor模式

grpc-go與actor模式

grpc-go與actor模式

(金慶的專欄 2018.6)

grpc-go伺服器的每個請求都在一個獨立的協程中執行。
網遊伺服器中,一般請求會呼叫遊戲房間的方法,而房間是一個獨立的協程。
可以將房間實現為actor,grpc請求通過Call()或Post()方法來執行。
其中Call()會等待返回,而Post()會非同步執行無返回值。

type Room struct {
    // actC 是其他協程向Room協程傳送動作的Channel,協程中將依次執行動作。
    // Action 動作, 是無引數無返回值的函式.
    actC chan func()

    ...
}

// Run 執行房間協程.
func (r *Room) Run() { ticker := time.NewTicker(20 * time.Millisecond) defer ticker.Stop() for r.running { select { case act := <-r.actC: act() case <-ticker.C: r.tick() } } } // Call calls a function f and returns the result.
// f runs in the Room's goroutine. func (r *Room) Call(f func() interface{}) interface{} { // 結果從ch返回 ch := make(chan interface{}, 1) r.actC <- func() { ch <- f() } // 等待直到返回結果 return <-ch } // Post 將一個動作投遞到內部協程中執行. func (r *Room) Post(f func()) { r.actC <- f }

grpc服務方法如:

func (m *RoomService) Test(ctx context.Context, req *pb.TestReq) (*pb.TestResp, error) {
    conn := conn_mgr.GetConn(ctx)
    if conn == nil {
        return nil, fmt.Errorf("can not find connection")
    }

    room := conn.GetRoom()
    resp := room.Call(func() interface{} {
        return room.Test(req)
    })

    return resp.(*pb.TestResp), nil
}