Help us shape the future of Go! Take the 2026 Go Developer Survey

health

package
v1.16.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2026 License: Apache-2.0 Imports: 6 Imported by: 1

Documentation

Overview

Package health — ЕДИНСТВЕННЫЙ в дереве носитель разведённых живости и готовности.

Готовность (`/readyz`) строится из ИМЕНОВАННЫХ проверок критичных зависимостей (база / канал к владельцу прав / дренер регистраций / исполнитель операций). Отказ зависимости снимает под из ротации (503), а живость (`/healthz`) при этом остаётся 200 — она зависит ТОЛЬКО от процесса, чтобы блип зависимости не вызвал шторм перезапусков. Каждый чекер ограничен собственным сроком: зависшая зависимость считается недоступной, но не вешает обработчик.

На гашении SetShuttingDown переводит `/readyz` в 503 (kubelet перестаёт слать трафик) ДО остановки gRPC-серверов.

Почему носитель ОДИН, а не по копии на сервис

Копий было три, и они были кодом идентичны — то есть один механизм, о котором дерево говорило трижды. Разойтись им было нечем: копии не собираются вместе и друг друга не читают, поэтому расхождение пришло бы молча. Замер, из которого это выведено (задача продукта #1655): трём сервисам из семи готовность требовалось завести впервые, и заведение по месту дало бы ШЕСТЬ копий вместо трёх (`architecture.md` §«Переиспользование через общий фундамент pkg/»).

Чего этот пакет НЕ решает

ЧТО именно проверяет каждая зависимость — вопрос композиционного корня: он один знает, какая база у сервиса своя и к кому он ходит. Пакет отвечает лишь за то, чтобы ответ был РАЗВЕДЁН на два и чтобы ни один чекер не мог подвесить обработчик.

Index

Constants

This section is empty.

Variables

View Source
var ErrDependencyNotWired = errors.New("dependency not wired yet")

ErrDependencyNotWired — зависимость объявлена корнем, но её носитель ещё не установлен. Причина «не готов» без раскрытия внутренних деталей наружу.

Functions

This section is empty.

Types

type Aggregator

type Aggregator struct {
	// contains filtered or unexported fields
}

Aggregator агрегирует readiness по набору чекеров и разводит liveness/readiness. Потокобезопасен (shutting — под mutex'ом; чекеры read-only).

func New

func New(checkers []Checker, opts ...Option) *Aggregator

New конструирует Aggregator поверх набора чекеров.

func (*Aggregator) Evaluate

func (a *Aggregator) Evaluate(ctx context.Context) (bool, []string)

Evaluate прогоняет все чекеры конкурентно с per-checker bounded-timeout и возвращает готовность + имена упавших зависимостей (в порядке объявления чекеров). Результат зеркалится в observer.

func (*Aggregator) LiveHandler

func (a *Aggregator) LiveHandler() http.HandlerFunc

LiveHandler — liveness probe. 200 `ok`, пока процесс жив и не в shutdown. НЕ зависит от внешних зависимостей (защита от restart-storm).

func (*Aggregator) ReadyHandler

func (a *Aggregator) ReadyHandler() http.HandlerFunc

ReadyHandler — readiness probe. 200 `{"status":"ready"}`, когда все критичные зависимости здоровы; 503 со списком упавших — иначе; 503 `{"status":"shutting_down"}` на graceful-shutdown.

func (*Aggregator) SetShuttingDown

func (a *Aggregator) SetShuttingDown()

SetShuttingDown помечает процесс в состоянии graceful-shutdown — readiness сразу флипает в 503, liveness тоже отдаёт 503 (процесс гасится).

type Checker

type Checker struct {
	Name  string
	Check func(ctx context.Context) error
}

Checker — именованная проверка одной зависимости. Check возвращает nil, если зависимость здорова; любая ошибка (или таймаут) трактуется как down.

type Option

type Option func(*Aggregator)

Option — функциональная опция Aggregator.

func WithResultObserver

func WithResultObserver(f func(dependency string, up bool)) Option

WithResultObserver подключает зеркало результата readiness (напр. dependency_up Prometheus-gauge): вызывается на каждый чекер при каждой оценке.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout задаёт per-checker бюджет (дефолт 1s).

type Slot

type Slot struct {
	// contains filtered or unexported fields
}

Slot — зависимость, чей носитель появляется ПОЗЖЕ поверхности.

Зачем

Диагностическая поверхность поднимается РАНО и намеренно: пока её нет, проба живости получает отказ соединения, и медленный старт читается kubelet'ом как мёртвый процесс — то есть шторм перезапусков ровно там, где процесс исправно поднимается. Часть зависимостей при этом ещё не создана: соединение с соседом набирается ниже по тексту корня.

Прямое замыкание на переменную корня здесь негодно ДВАЖДЫ: обработчик читает её из другой горутины (гонка, и `-race` это покажет), а до присваивания он увидит нулевое значение и объявит зависимость исправной. Slot закрывает оба: доступ синхронизирован, а до установки ответ — НЕ ГОТОВ.

Умолчание выбрано fail-closed осознанно: неустановленная зависимость есть «ответа нет», а неполученный ответ не является «да».

func (*Slot) Check

func (s *Slot) Check(ctx context.Context) error

Check — тело чекера. До Install отвечает ErrDependencyNotWired: «носителя ещё нет» и «носитель отвечает» обязаны быть различимы, иначе окно старта молча зачитывается в готовность.

func (*Slot) Checker

func (s *Slot) Checker(name string) Checker

Checker собирает Slot в именованную проверку.

func (*Slot) Install

func (s *Slot) Install(check func(ctx context.Context) error)

Install подключает носителя зависимости. Повторный вызов заменяет прежнего — корень вправе пересобрать соединение, не пересобирая поверхность.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL