Реализация таймера для метода rp c - PullRequest
1 голос
/ 16 февраля 2020

У меня есть сервер Go RP C, который обслуживает запросы клиентов. Клиент запрашивает работу (или задачу) с сервера, а сервер назначает задачу клиенту. Сервер ожидает, что работники (или клиенты) выполнят sh любую задачу в течение определенного времени. Поэтому на стороне сервера требуется механизм обратного вызова события тайм-аута.

Вот то, что я пробовал до сих пор.

func (l *Listener) RequestHandler(request string, reply string) error {
    // some other work
    // ....
    _timer := time.NewTimer(time.Second * 5) // timer for 2 seconds
    go func() {
        // simulates a client not replying case, with timeout of 2 sec
        y := <-_timer.C
        fmt.Println("TimeOut for client")
        // revert state changes becasue of client fail
    }()

    // set reply
    // update some states
    return nil
}

В приведенном выше фрагменте для каждого запроса от работника (или клиент) обработчик на стороне сервера запускает таймер и программу. Программа отменяет изменения, сделанные функцией-обработчиком, перед отправкой ответа клиенту.

Есть ли способ создать «набор таймеров» и заблокировать ожидание «набора таймеров»? Кроме того, всякий раз, когда таймер истекает, блокирующее ожидание пробуждается и предоставляет нам ручки таймера. В зависимости от типа таймера мы можем выполнять разные функции обработчика истечения во время выполнения.

Я пытаюсь реализовать аналогичный механизм в Go, который мы можем реализовать в C ++ с помощью timerfd with epoll.

Полный код для примера реализации таймеров в Go. сервер. go и клиент. go.

1 Ответ

4 голосов
/ 16 февраля 2020

Я предлагаю вам изучить контекст пакет

, это можно сделать так:

func main() {
    c := context.Background()
    wg := &sync.WaitGroup{}
    f(c, wg)
    wg.Wait()
}

func f(c context.Context, wg *sync.WaitGroup) {
    c, _ = context.WithTimeout(c, 3*time.Second)
    wg.Add(1)

    go func(c context.Context) {
        defer wg.Done()
        select {
        case <-c.Done():
            fmt.Println("f() Done:", c.Err())
            return
        case r := <-time.After(5 * time.Second):
            fmt.Println("f():", r)
        }
    }(c)
}

в основном вы инициируете базовый контекст и затем извлекаете другие контексты из него, когда контекст завершается, либо передавая время или вызывая его close , он закрывает свой Done канал и Done канал все контексты, которые получены из него.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...