Как предотвратить сбои программы Go после случайной паники? - PullRequest
0 голосов
/ 18 мая 2018

Подумайте о большом проекте, который обрабатывает тонны одновременных запросов, обрабатываемых его собственной программой.Бывает, что в коде есть ошибка, и один из этих запросов вызовет панику из-за нулевой ссылки.

В Java, C # и многих других языках это приведет к исключению, которое остановитзапрос без какого-либо вреда для других здоровых запросов.В го, это привело бы к краху всей программы.

AFAIK, мне нужно было бы иметь recover() для каждого нового создания рутины.Это единственный способ предотвратить сбой всей программы?

ОБНОВЛЕНИЕ: добавление вызова recover() для каждого создания маршрутизации кажется приемлемым.А как насчет сторонних библиотек?Если третье лицо создает процедуры без recover() безопасной сети, кажется, что НИЧЕГО не нужно делать.

Ответы [ 2 ]

0 голосов
/ 19 мая 2018

Если вы выберете отсрочку восстановления всего, я предлагаю потратить некоторое время, чтобы убедиться, что собрано четкое сообщение об ошибке с достаточным количеством информации, чтобы быстро на него реагировать.

Написание паникисообщение для stderr / stdout не очень хорошее, так как будет очень трудно найти причину проблемы.По моему опыту, лучший подход - потратить немного времени на то, чтобы ваши программы Go обрабатывали ошибки разумным образом.Например, errors.Wrap из " github.com / pkg / errors " позволяет обернуть все ошибки и получить трассировку стека.

Восстановление паники часто является неизбежным злом.Как вы говорите, не идеальный сбой всей программы только потому, что один запрос вызвал панику.В большинстве случаев восстановление паники не приведет к обратному эффекту, но программа может оказаться в неопределенном состоянии, которое невозможно восстановить, которое может исправить только перезапуск вручную.При этом я предлагаю в этом случае убедиться, что ваша программа Go предоставляет способ создания дампа ядра.

Вот как записать дамп ядра в stderr, когда SIGQUIT отправляется в программу Go (например,. kill pid -QUIT)

go func() {
    // Based on answers to this stackoverflow question:
    // https://stackoverflow.com/questions/19094099/how-to-dump-goroutine-stacktraces
    sigs := make(chan os.Signal, 1)
    signal.Notify(sigs, syscall.SIGQUIT)
    for {
        <-sigs

        fmt.Fprintln(os.Stderr, "=== received SIGQUIT ===")
        fmt.Fprintln(os.Stderr, "*** goroutine dump...")

        var buf []byte
        var bufsize int
        var stacklen int

        // Create a stack buffer of 1MB and grow it to at most 100MB if
        // necessary
        for bufsize = 1e6; bufsize < 100e6; bufsize *= 2 {
            buf = make([]byte, bufsize)
            stacklen = runtime.Stack(buf, true)
            if stacklen < bufsize {
                break
            }
        }
        fmt.Fprintln(os.Stderr, string(buf[:stacklen]))
        fmt.Fprintln(os.Stderr, "*** end of dump")
    }
}()
0 голосов
/ 19 мая 2018

нет способа справиться с паникой без функции восстановления. Хорошей практикой будет использование функции промежуточного программного обеспечения для безопасной функции, ознакомьтесь с этим фрагментом

https://play.golang.org/p/d_fQWzXnlAm

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