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
}

猜你喜欢

转载自blog.csdn.net/jq0123/article/details/80662686