I controlli di salute sono cruciali per il monitoraggio e l’orchestrazione dei servizi. Aiutano ad assicurare che il tuo servizio funzioni correttamente e che tutte le sue dipendenze siano disponibili. Clue fornisce un sistema standard di controllo della salute che monitora le dipendenze del servizio e riporta il loro stato, rendendo facile l’integrazione con orchestratori di container e sistemi di monitoraggio.
Il sistema di controllo della salute di Clue fornisce un monitoraggio completo della salute del servizio:
Configurare i controlli di salute nel tuo servizio è semplice. Ecco un esempio base:
// Crea checker di salute
checker := health.NewChecker()
// Monta endpoint di controllo salute
// Questo crea un endpoint GET /health che restituisce lo stato del servizio
mux.Handle("GET", "/health", health.Handler(checker))
Con questo setup base, il tuo servizio acquisisce diverse capacità essenziali di monitoraggio della salute. Ottieni un endpoint standardizzato di controllo della salute che i sistemi esterni possono interrogare in modo affidabile per verificare lo stato del tuo servizio. L’endpoint restituisce risposte in formato JSON, rendendo facile per gli strumenti di monitoraggio analizzare ed elaborare i dati sulla salute. Il sistema usa codici di stato HTTP standard per indicare chiaramente se il tuo servizio è in salute o sta riscontrando problemi. Inoltre, aggrega automaticamente lo stato di tutte le dipendenze del tuo servizio, dandoti una vista completa della salute del tuo sistema a colpo d’occhio.
L’endpoint di controllo della salute restituisce una risposta JSON che include lo stato di tutte le dipendenze monitorate:
{
"status": {
"PostgreSQL": "OK",
"Redis": "OK",
"PaymentService": "NOT OK"
},
"uptime": 3600,
"version": "1.0.0"
}
La risposta include:
Codici di stato HTTP:
Per rendere un servizio o una dipendenza controllabile per la salute, implementa
l’interfaccia Pinger
. Questa interfaccia è semplice ma potente:
// Interfaccia Pinger
type Pinger interface {
Name() string // Identificatore unico per la dipendenza
Ping(context.Context) error // Controlla se la dipendenza è in salute
}
// Controllo salute database
// Esempio di implementazione per un database PostgreSQL
type DBClient struct {
db *sql.DB
}
func (c *DBClient) Name() string {
return "PostgreSQL"
}
func (c *DBClient) Ping(ctx context.Context) error {
// Usa la funzionalità di ping integrata del database
return c.db.PingContext(ctx)
}
// Controllo salute Redis
// Esempio di implementazione per una cache Redis
type RedisClient struct {
client *redis.Client
}
func (c *RedisClient) Name() string {
return "Redis"
}
func (c *RedisClient) Ping(ctx context.Context) error {
// Usa il comando PING di Redis
return c.client.Ping(ctx).Err()
}
Quando implementi i controlli di salute, ci sono diversi fattori importanti da considerare. Prima di tutto, i controlli di salute dovrebbero essere leggeri ed eseguire velocemente per evitare di impattare le prestazioni del tuo servizio. Questo è particolarmente importante poiché i controlli di salute potrebbero essere chiamati frequentemente dai sistemi di monitoraggio.
La gestione appropriata dei timeout è anche critica. Ogni controllo di salute dovrebbe rispettare i timeout passati via context e ritornare prontamente se il timeout viene raggiunto. Questo previene che i controlli di salute si blocchino e potenzialmente causino problemi più ampi nel sistema.
I messaggi di errore restituiti dai controlli di salute dovrebbero essere chiari e azionabili. Quando un controllo fallisce, il messaggio di errore dovrebbe fornire dettagli sufficienti per gli operatori per comprendere e affrontare rapidamente il problema. Questo potrebbe includere codici di errore specifici, stati dei componenti o suggerimenti per il troubleshooting.
Per controlli di salute che sono intensivi in termini di risorse o colpiscono servizi esterni, considera l’implementazione di un meccanismo di caching. Questo può aiutare a ridurre il carico mentre fornisce ancora uno stato di salute ragionevolmente attuale. La durata della cache dovrebbe essere bilanciata rispetto alle tue necessità di accuratezza - durate più brevi danno risultati più attuali ma aumentano il carico.
Monitorare la salute dei servizi downstream è cruciale per i sistemi distribuiti. Ecco come implementare controlli di salute per diversi tipi di servizi:
// Controllo salute servizio HTTP
type ServiceClient struct {
name string
client *http.Client
url string
}
func (c *ServiceClient) Name() string {
return c.name
}
func (c *ServiceClient) Ping(ctx context.Context) error {
// Crea richiesta con context per gestione timeout
req, err := http.NewRequestWithContext(ctx,
"GET", c.url+"/health", nil)
if err != nil {
return err
}
// Esegui richiesta di controllo salute
resp, err := c.client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
// Controlla stato risposta
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("servizio non in salute: %d", resp.StatusCode)
}
return nil
}
// Controllo salute servizio gRPC
type GRPCClient struct {
name string
conn *grpc.ClientConn
}
func (c *GRPCClient) Name() string {
return c.name
}
func (c *GRPCClient) Ping(ctx context.Context) error {
// Usa protocollo standard di controllo salute gRPC
return c.conn.Invoke(ctx,
"/grpc.health.v1.Health/Check",
&healthpb.HealthCheckRequest{},
&healthpb.HealthCheckResponse{})
}
Oltre ai controlli di connettività base, puoi implementare controlli di salute personalizzati per requisiti specifici del business:
// Controllo logica di business personalizzata
type BusinessCheck struct {
store *Store
}
func (c *BusinessCheck) Name() string {
return "BusinessLogic"
}
func (c *BusinessCheck) Ping(ctx context.Context) error {
// Controlla condizioni di business critiche
ok, err := c.store.CheckConsistency(ctx)
if err != nil {
return err
}
if !ok {
return errors.New("rilevata inconsistenza dati")
}
return nil
}
// Controllo risorse di sistema
type ResourceCheck struct {
threshold float64
}
func (c *ResourceCheck) Name() string {
return "SystemResources"
}
func (c *ResourceCheck) Ping(ctx context.Context) error {
// Controlla utilizzo memoria
var m runtime.MemStats
runtime.ReadMemStats(&m)
memoryUsage := float64(m.Alloc) / float64(m.Sys)
if memoryUsage > c.threshold {
return fmt.Errorf("utilizzo memoria troppo alto: %.2f", memoryUsage)
}
return nil
}
Configura i controlli di salute del tuo servizio in Kubernetes usando le probe. Questo esempio mostra sia probe di liveness che di readiness:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myservice
spec:
template:
spec:
containers:
- name: myservice
image: myservice:latest
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 3
periodSeconds: 3
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
Controlli delle Dipendenze:
Tempi di Risposta:
Gestione Errori:
Sicurezza:
Per maggiori informazioni sui controlli di salute:
Pacchetto Health di Clue Documentazione completa delle capacità di controllo salute di Clue
Probe Kubernetes Documentazione ufficiale Kubernetes sulla configurazione delle probe
Pattern di Controllo Salute Pattern comuni e best practice per API di controllo salute