grpcclient

package
v1.3.1 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package grpcclient — горизонтальный cross-cutting helper для client-side gRPC keepalive. Единая точка истины для keepalive-параметров inter-service dial-сайтов (compute dialPeer, iam subject-drainer, vpc-sdk).

Проблема: bare-dial-сайты (`grpc.NewClient(addr, …)` без keepalive) держат conn'ы, которые между всплесками трафика простаивают и становятся half-open; первый RPC всплеска висит ~30с на переустановке TCP/HTTP2. keepalive-пинги проактивно обнаруживают мертвый conn и переустанавливают его.

Серверная сторона, принимающая idle keepalive (PermitWithoutStream=true), должна разрешать частые пинги — см. grpcsrv.DefaultKeepaliveEnforcement.

Package grpcclient — tls.go: opt-in mTLS client-credentials helper.

TLSClientCreds is the single source of truth for assembling client-side TLS transport credentials for inter-service gRPC dials, by analogy with the keepalive dial-option helper.

Behavior contract:

  • enable=false → insecure transport-credentials (current plaintext dial, dev backward-compat); cert files are NOT read.
  • enable=true → mTLS: presents client-cert (cert_file/key_file), verifies the server-cert against ca_files, and checks server_name against the server-cert SAN (client-cert + server-CA + server-name).
  • enable=true + empty cert_file AND key_file → one-way TLS: NO client-cert is presented (still verifies server-cert via ca_files + server_name). This is not a normal production edge — it exists so a require-and-verify server correctly rejects a cert-less client → Unavailable.
  • enable=true + unreadable/garbage cert / empty ca_files / empty server_name → error (fail-closed; never a silent insecure fallback).

Cert files are read once at startup; rotation = pod restart.

Index

Constants

View Source
const (
	// DefaultKeepaliveTime — интервал ping'а: агрессивный 10s, чтобы поймать
	// half-open до следующего всплеска в kind, где idle-flow умирает быстрее 30s.
	DefaultKeepaliveTime = 10 * time.Second
	// DefaultKeepaliveTimeout — ack-deadline = треть интервала (инвариант
	// «таймаут = треть Time»).
	DefaultKeepaliveTimeout = DefaultKeepaliveTime / 3
)

Variables

This section is empty.

Functions

func DialPeer

func DialPeer(opts PeerDialOptions) (*grpc.ClientConn, error)

DialPeer — соединение с соседом. Не набирает: `grpc.NewClient` откладывает соединение до первого вызова, поэтому отказ здесь означает негодные параметры, а не недоступность соседа.

func KeepaliveDialOption

func KeepaliveDialOption(permitWithoutStream bool) grpc.DialOption

KeepaliveDialOption — grpc.DialOption с дефолтными keepalive-параметрами.

func KeepaliveParams

func KeepaliveParams(permitWithoutStream bool) keepalive.ClientParameters

KeepaliveParams — стандартные client keepalive-параметры.

permitWithoutStream=true для преимущественно-idle conn'ов (authz, drainer): пинги держат conn теплым даже без активных стримов — прямо лечит half-open-столл. Для активно используемых conn'ов — false (там всегда есть трафик).

func PeerConnectParams

func PeerConnectParams(dialTimeout time.Duration) grpc.ConnectParams

PeerConnectParams — отступ переподключения. Величины дословно те же, что у снятого строителя.

func PeerServiceConfigJSON

func PeerServiceConfigJSON(retries uint, roundRobin bool) string

PeerServiceConfigJSON — конфигурация службы: политика повтора и, по просьбе, распределение. Пустая строка означает «объявлять нечего» — а не «объявлено пустое»: повтор без попыток и балансировщик без адресов суть разные вещи.

func PeerTarget

func PeerTarget(endpoint string, roundRobin bool) string

PeerTarget — адрес в форме, которую понимает резолвер gRPC. Схема пишется явно; разбор разобран в шапке файла.

func TLSClientCreds

func TLSClientCreds(cfg TLSClient) (grpc.DialOption, error)

TLSClientCreds returns the grpc.DialOption carrying the transport credentials for this config. See package doc for the behavior contract.

func TLSClientTransportCreds

func TLSClientTransportCreds(cfg TLSClient) (credentials.TransportCredentials, error)

TLSClientTransportCreds returns the raw credentials.TransportCredentials for this config — the same building block TLSClientCreds wraps into a DialOption. Callers that dial through a builder taking TransportCredentials (rather than a DialOption) use this directly, keeping a single source of truth for the behavior contract.

Types

type PeerDialOptions

type PeerDialOptions struct {
	// Endpoint — адрес соседа: `host:port`, либо адрес, сам назвавший резолвер.
	Endpoint string
	// Creds — транспортные учётные данные. nil → insecure.
	Creds credentials.TransportCredentials
	// Retries — сколько раз повторить вызов сверх исходной попытки. 0 → без повтора.
	Retries uint
	// DialTimeout — цель отступа переподключения.
	DialTimeout time.Duration
	// KeepAliveTime — интервал опроса. 0 → без keepalive.
	KeepAliveTime time.Duration
	// UserAgent — представление клиента.
	UserAgent string
	// RoundRobin — распределять вызовы по ВСЕМ адресам имени. Требует резолвера
	// dns: passthrough отдаёт один адрес.
	RoundRobin bool
}

PeerDialOptions — параметры соединения с соседним сервисом.

type TLSClient

type TLSClient struct {
	// Enable toggles mTLS for this dial. Zero-value false ⇒ insecure.
	Enable bool
	// CertFile is the PEM client-certificate presented to the server.
	CertFile string
	// KeyFile is the PEM private key for CertFile.
	KeyFile string
	// CAFiles are PEM CA bundles used to verify the server-cert.
	CAFiles []string
	// ServerName is checked against the server-cert SAN.
	ServerName string
}

TLSClient is a HORIZONTAL, per-edge client-side TLS value-struct. It is a plain value struct with no process-wide TLS singleton: every dial-site receives its own TLSClientCreds argument (no global singletons outside cmd/).

It carries NO absolute envconfig tags ON PURPOSE. This struct is embedded by every service under its own per-edge (per-peer) dial config field; an absolute tag (e.g. KACHO_COMPUTE_TLS_CLIENT_ENABLE) would collapse every dial-edge onto the same env names and break per-edge independence. Instead the env name is derived from the hierarchy of field names: the SERVICE owns the edge name by choosing the parent field and loading with config.LoadPrefixed("KACHO_<DOMAIN>", &cfg).

Example — a service that dials two peers:

type Config struct {
	IAM grpcclient.TLSClient // → KACHO_COMPUTE_IAM_ENABLE, ..._CAFILES, ...
	VPC grpcclient.TLSClient // → KACHO_COMPUTE_VPC_ENABLE, ..._CAFILES, ...
}
_ = config.LoadPrefixed("KACHO_COMPUTE", &cfg) // each dial-edge independent

This yields the KACHO_<DOMAIN>_<EDGE>_<NAME> convention with true per-edge prefixing: distinct dial-edges in one process resolve to distinct env blocks (one process may run an mTLS client and an insecure server simultaneously).

Jump to

Keyboard shortcuts

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