dongwen9051 2018-05-11 10:40
浏览 101
已采纳

去不立即响应GET请求,完成报价后立即响应

I'm new to Go programming and I try to build API for a multiplayer game. If I make GET req to the http://localhost:8080/create_game/gameName . Server response to the request when ticker is done. I need to get response from a server instantly but I got it when ticker is over and game is timeouted and deleted.

Here is my code:

var clients = make(map[*websocket.Conn]bool)
var broadcast = make(chan Game)

//GAME_TIMEOUT in seconds
const GAME_TIMEOUT = 20

//ID generating
var genID = 0

var games = []Game{}

var msg json.RawMessage

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

type GameToSend struct {
    Type string `json:"type"`
    ID   int    `json:"id"`
    Name string `json:"name"`
}
type Game struct {
    ID    int              `json:"id"`
    Name  string           `json:"name"`
    Timer <-chan time.Time `json:"timestamp"`
}

func main() {
    router := mux.NewRouter()
    router.HandleFunc("/create_game/{name}", createGame)
    router.HandleFunc("/game_events", handleConnections)
    http.ListenAndServe(":8080", router)
}

func handleConnections(w http.ResponseWriter, r *http.Request) {

    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()
    clients[conn] = true
    for _, game := range games {
        conn.WriteJSON(GameToSend{"game.created", game.ID, game.Name})
    }
    for {
        err := conn.ReadJSON(&msg)
        if err != nil {
            fmt.Println(err)
        } else {
            fmt.Println(msg)
        }
    }
}

func broadcastGame(game GameToSend) {
    for conn := range clients {
        conn.WriteJSON(game)
    }
}

func createGame(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)
    genID++
    game := Game{genID, params["name"], time.NewTimer(GAME_TIMEOUT * time.Second).C}
    games = append(games, game)
    broadcastGame(GameToSend{"game.created", game.ID, game.Name})
    w.Write([]byte("response"))
    checkTimeout(genID)
}

func deleteGame(actionType string, i int) {
    for index, game := range games {
        if game.ID == i {
            broadcastGame(GameToSend{actionType, games[index].ID, games[index].Name})
            games = games[:index+copy(games[index:], games[index+1:])]
        }
    }
}

func checkTimeout(id int) {
    for _, game := range games {
        if game.ID == id {
            <-game.Timer
            deleteGame("game.timeout", id)
        }
    }
}

any idea how to fix it?

  • 写回答

1条回答 默认 最新

  • dtkl55257 2018-05-11 11:22
    关注

    There are a number of things you could change, but one of them is in general don't run potentially long running tasks in the code that is responding to clients. Imagine you have millions of games, so many that each call to checkTimeout takes a second to iterate over all the games. Every request would have a one second delay to get a complete response, not great. It would be better to signal another goroutine should iterate over the games and clean up expired ones, that way you can return immediately to the client while the clean up happens in the background.

    Turns out I misread what you are doing, but the advice is still valid. In this case though the "long running function" actually waits until the timer expires before returning. That could be significantly longer than one second! Were you meaning to run that in a goroutine? go checkTimeout(genID)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图