Golang: использование systemd для перезапуска и развертывания с нулевым временем простоя

Golang: использование systemd для перезапуска и развертывания с нулевым временем простоя

22 декабря 2022 г.

Во время перезапуска ваш API может быть недоступен в течение короткого периода времени, чтобы остановить старый экземпляр приложения и запустить новый. Это можно исправить, добавив еще одно приложение (прокси), которое прослушивает данные от имени основного приложения и каким-то образом передает данные основному приложению.

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

Настроив сокет systemd, вы можете указать systemd прослушивать настроенные порты и запускать службу с копией прослушиваемых сокетов. При перезапуске данные не теряются, а сохраняются в буферах ОС.

Системный сокет

Вы можете настроить сокет systemd, создав файл /lib/systemd/system/myapp.socket, например, следующий сокет прослушивает порт 80, но вы можете добавить столько портов, сколько вам нужно:

[Socket]
ListenStream = 80
#ListenStream = 443
BindIPv6Only = both
Service      = myapp.service

[Install]
WantedBy = sockets.target

Вам также необходимо настроить сопутствующий сервис systemd, создав файл myapp.service:

[Unit]
Description = myapp
After       = network.target

[Service]
Type = simple

ExecStart = /bin/myapp
ExecStop  = /bin/kill $MAINPID
KillMode  = none

[Install]
WantedBy = multi-user.target

Использование сокетов Systemd

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

go get github.com/coreos/go-systemd/v22

А затем используйте его следующим образом:

import "github.com/coreos/go-systemd/v22/activation"

func main() {
    listeners, err := activation.Listeners()
    if err != nil {
        return err
    }

    httpLn := listeners[0]
    //httpsLn := listeners[1]

    httpServer := &http.Server{
        ReadHeaderTimeout: 5 * time.Second,
        ReadTimeout:       5 * time.Second,
        WriteTimeout:      5 * time.Second,
        IdleTimeout:       60 * time.Second,
        Handler:           router,
    }
    if err := httpServer.Serve(httpLn); err != nil {
        log.Printf("Serve failed: %s", err)
    }
}

В качестве маршрутизатора Golang вы можете попробовать бунроутер.

Перезапуск приложения

Во-первых, вам нужно запустить настроенный сокет systemd:

sudo systemctl start myapp.socket

А затем проверьте, что сокет был успешно создан:

sudo systemctl status myapp.socket

Systemd автоматически запустит службу по первому запросу или в случае сбоя службы. Вы также можете вручную перезапустить службу во время развертывания:

sudo systemctl restart myapp.service

Отслеживание

Uptrace – это конкурент DataDog с открытым исходным кодом, который предлагает интуитивно понятный конструктор запросов, подробные информационные панели и правила оповещения. и интеграции для большинства языков и фреймворков. Он может обрабатывать миллиарды диапазонов и метрик на одном сервере и позволяет отслеживать ваши приложения в 10 раз дешевле.

Uptrace использует базу данных ClickHouse для хранения трассировок, метрик и логов. Вы можете использовать его для мониторинга приложений и настройки автоматических оповещений для получения уведомлений по электронной почте, Slack, Telegram и т. д.

Вы можете начать работу с Uptrace, загрузив пакет DEB/RPM или предварительно скомпилированный двоичный файл Go.


Также опубликовано здесь


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE