70 lines
1.7 KiB
Go
70 lines
1.7 KiB
Go
package healthcheck
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// Response 是 gateway HTTP health endpoint 的稳定 JSON 契约。
|
|
type Response struct {
|
|
Status string `json:"status"`
|
|
Service string `json:"service"`
|
|
NodeID string `json:"node_id"`
|
|
TimeUnixMS int64 `json:"time_unix_ms"`
|
|
Checks []Check `json:"checks,omitempty"`
|
|
}
|
|
|
|
// HTTPHandler 暴露 /healthz/live 和 /healthz/ready 两个只读入口。
|
|
type HTTPHandler struct {
|
|
state *State
|
|
}
|
|
|
|
// NewHTTPHandler 创建 gateway health HTTP handler。
|
|
func NewHTTPHandler(state *State) *HTTPHandler {
|
|
return &HTTPHandler{state: state}
|
|
}
|
|
|
|
// Live 返回进程自身是否仍可运行。
|
|
func (h *HTTPHandler) Live(writer http.ResponseWriter, request *http.Request) {
|
|
checks := h.state.Live()
|
|
statusCode := http.StatusOK
|
|
if !Healthy(checks) {
|
|
statusCode = http.StatusInternalServerError
|
|
}
|
|
|
|
h.write(writer, statusCode, checks)
|
|
}
|
|
|
|
// Ready 返回当前 gateway 实例是否可以接新 HTTP 请求。
|
|
func (h *HTTPHandler) Ready(writer http.ResponseWriter, request *http.Request) {
|
|
checks := h.state.Ready(request.Context())
|
|
statusCode := http.StatusOK
|
|
if !Healthy(checks) {
|
|
statusCode = http.StatusServiceUnavailable
|
|
}
|
|
|
|
h.write(writer, statusCode, checks)
|
|
}
|
|
|
|
func (h *HTTPHandler) write(writer http.ResponseWriter, statusCode int, checks []Check) {
|
|
status := componentStatus
|
|
if !Healthy(checks) {
|
|
status = failStatus
|
|
}
|
|
|
|
response := Response{
|
|
Status: status,
|
|
Service: h.state.ServiceName(),
|
|
NodeID: h.state.NodeID(),
|
|
TimeUnixMS: time.Now().UnixMilli(),
|
|
}
|
|
if status != componentStatus {
|
|
response.Checks = checks
|
|
}
|
|
|
|
writer.Header().Set("Content-Type", "application/json")
|
|
writer.WriteHeader(statusCode)
|
|
_ = json.NewEncoder(writer).Encode(response)
|
|
}
|