Browse Source

Merge pull request #2112 from xiang90/health

etcdhttp: add health endpoint
Xiang Li 11 years ago
parent
commit
3ec91ead88
1 changed files with 34 additions and 2 deletions
  1. 34 2
      etcdserver/etcdhttp/client.go

+ 34 - 2
etcdserver/etcdhttp/client.go

@@ -37,6 +37,7 @@ import (
 	"github.com/coreos/etcd/etcdserver/etcdserverpb"
 	"github.com/coreos/etcd/etcdserver/stats"
 	"github.com/coreos/etcd/pkg/types"
+	"github.com/coreos/etcd/raft"
 	"github.com/coreos/etcd/store"
 	"github.com/coreos/etcd/version"
 )
@@ -46,7 +47,8 @@ const (
 	deprecatedMachinesPrefix = "/v2/machines"
 	membersPrefix            = "/v2/members"
 	statsPrefix              = "/v2/stats"
-	versionPrefix            = "/version"
+	healthPath               = "/health"
+	versionPath              = "/version"
 )
 
 // NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests.
@@ -74,7 +76,8 @@ func NewClientHandler(server *etcdserver.EtcdServer) http.Handler {
 
 	mux := http.NewServeMux()
 	mux.HandleFunc("/", http.NotFound)
-	mux.HandleFunc(versionPrefix, serveVersion)
+	mux.Handle(healthPath, healthHandler(server))
+	mux.HandleFunc(versionPath, serveVersion)
 	mux.Handle(keysPrefix, kh)
 	mux.Handle(keysPrefix+"/", kh)
 	mux.HandleFunc(statsPrefix+"/store", sh.serveStore)
@@ -281,6 +284,35 @@ func (h *statsHandler) serveLeader(w http.ResponseWriter, r *http.Request) {
 	w.Write(stats)
 }
 
+// TODO: change etcdserver to raft interface when we have it.
+//       add test for healthHeadler when we have the interface ready.
+func healthHandler(server *etcdserver.EtcdServer) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		if !allowMethod(w, r.Method, "GET") {
+			return
+		}
+
+		if uint64(server.Leader()) == raft.None {
+			http.Error(w, `{"health": "false"}`, http.StatusServiceUnavailable)
+			return
+		}
+
+		// wait for raft's progress
+		index := server.Index()
+		for i := 0; i < 3; i++ {
+			time.Sleep(250 * time.Millisecond)
+			if server.Index() > index {
+				w.WriteHeader(http.StatusOK)
+				w.Write([]byte(`{"health": "true"}`))
+				return
+			}
+		}
+
+		http.Error(w, `{"health": "false"}`, http.StatusServiceUnavailable)
+		return
+	}
+}
+
 func serveVersion(w http.ResponseWriter, r *http.Request) {
 	if !allowMethod(w, r.Method, "GET") {
 		return