...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package grpcproxy
16
17 import (
18 "context"
19 "fmt"
20 "net/http"
21 "time"
22
23 "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
24 "go.etcd.io/etcd/client/v3"
25 "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp"
26 "go.uber.org/zap"
27 )
28
29
30 func HandleHealth(lg *zap.Logger, mux *http.ServeMux, c *clientv3.Client) {
31 if lg == nil {
32 lg = zap.NewNop()
33 }
34 mux.Handle(etcdhttp.PathHealth, etcdhttp.NewHealthHandler(lg, func(ctx context.Context, excludedAlarms etcdhttp.StringSet, serializable bool) etcdhttp.Health {
35 return checkHealth(c)
36 }))
37 }
38
39
40 func HandleProxyHealth(lg *zap.Logger, mux *http.ServeMux, c *clientv3.Client) {
41 if lg == nil {
42 lg = zap.NewNop()
43 }
44 mux.Handle(etcdhttp.PathProxyHealth, etcdhttp.NewHealthHandler(lg, func(ctx context.Context, excludedAlarms etcdhttp.StringSet, serializable bool) etcdhttp.Health {
45 return checkProxyHealth(c)
46 }))
47 }
48
49 func checkHealth(c *clientv3.Client) etcdhttp.Health {
50 h := etcdhttp.Health{Health: "false"}
51 ctx, cancel := context.WithTimeout(c.Ctx(), time.Second)
52 _, err := c.Get(ctx, "a")
53 cancel()
54 if err == nil || err == rpctypes.ErrPermissionDenied {
55 h.Health = "true"
56 } else {
57 h.Reason = fmt.Sprintf("GET ERROR:%s", err)
58 }
59 return h
60 }
61
62 func checkProxyHealth(c *clientv3.Client) etcdhttp.Health {
63 if c == nil {
64 return etcdhttp.Health{Health: "false", Reason: "no connection to proxy"}
65 }
66 h := checkHealth(c)
67 if h.Health != "true" {
68 return h
69 }
70 ctx, cancel := context.WithTimeout(c.Ctx(), time.Second*3)
71 ch := c.Watch(ctx, "a", clientv3.WithCreatedNotify())
72 select {
73 case <-ch:
74 case <-ctx.Done():
75 h.Health = "false"
76 h.Reason = "WATCH TIMEOUT"
77 }
78 cancel()
79 return h
80 }
81
View as plain text