From 0d3d4c5b01d67868d0a29dabd2dc1bd704cc43cd Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Tue, 26 May 2015 16:00:11 -0700 Subject: [PATCH] rafthttp: print out log when clusterID mismatch instead of exiting We have heard from several users that they do not expect a clusterID mismatch to kill the cluster. --- rafthttp/http.go | 16 +++++++++------- rafthttp/pipeline.go | 9 +++------ rafthttp/pipeline_test.go | 1 - rafthttp/stream.go | 5 +++++ 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/rafthttp/http.go b/rafthttp/http.go index fc8b77d32..4438d687d 100644 --- a/rafthttp/http.go +++ b/rafthttp/http.go @@ -126,6 +126,15 @@ func (h *streamHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } + wcid := h.cid.String() + w.Header().Set("X-Etcd-Cluster-ID", wcid) + + if gcid := r.Header.Get("X-Etcd-Cluster-ID"); gcid != wcid { + log.Printf("rafthttp: streaming request ignored due to cluster ID mismatch got %s want %s", gcid, wcid) + http.Error(w, "clusterID mismatch", http.StatusPreconditionFailed) + return + } + w.Header().Add("X-Server-Version", version.Version) var t streamType @@ -162,13 +171,6 @@ func (h *streamHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - wcid := h.cid.String() - if gcid := r.Header.Get("X-Etcd-Cluster-ID"); gcid != wcid { - log.Printf("rafthttp: streaming request ignored due to cluster ID mismatch got %s want %s", gcid, wcid) - http.Error(w, "clusterID mismatch", http.StatusPreconditionFailed) - return - } - wto := h.id.String() if gto := r.Header.Get("X-Raft-To"); gto != wto { log.Printf("rafthttp: streaming request ignored due to ID mismatch got %s want %s", gto, wto) diff --git a/rafthttp/pipeline.go b/rafthttp/pipeline.go index 4443d3e25..c11de3236 100644 --- a/rafthttp/pipeline.go +++ b/rafthttp/pipeline.go @@ -148,12 +148,9 @@ func (p *pipeline) post(data []byte) error { switch resp.StatusCode { case http.StatusPreconditionFailed: - err := fmt.Errorf("conflicting cluster ID with the target cluster (%s != %s)", resp.Header.Get("X-Etcd-Cluster-ID"), p.cid) - select { - case p.errorc <- err: - default: - } - return nil + log.Printf("rafthttp: request sent was ignored due to cluster ID mismatch (remote[%s]:%s, local:%s)", + uu.Host, resp.Header.Get("X-Etcd-Cluster-ID"), p.cid) + return fmt.Errorf("cluster ID mismatch") case http.StatusForbidden: err := fmt.Errorf("the member has been permanently removed from the cluster") select { diff --git a/rafthttp/pipeline_test.go b/rafthttp/pipeline_test.go index ce521fbd0..a543d7f9e 100644 --- a/rafthttp/pipeline_test.go +++ b/rafthttp/pipeline_test.go @@ -165,7 +165,6 @@ func TestPipelinePostErrorc(t *testing.T) { err error }{ {"http://localhost:2380", http.StatusForbidden, nil}, - {"http://localhost:2380", http.StatusPreconditionFailed, nil}, } for i, tt := range tests { picker := mustNewURLPicker(t, []string{tt.u}) diff --git a/rafthttp/stream.go b/rafthttp/stream.go index d5b377c55..7ca0a3831 100644 --- a/rafthttp/stream.go +++ b/rafthttp/stream.go @@ -424,6 +424,11 @@ func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) { case http.StatusNotFound: resp.Body.Close() return nil, fmt.Errorf("local member has not been added to the peer list of member %s", cr.to) + case http.StatusPreconditionFailed: + resp.Body.Close() + log.Printf("rafthttp: request sent was ignored due to cluster ID mismatch (remote[%s]:%s, local:%s)", + uu.Host, resp.Header.Get("X-Etcd-Cluster-ID"), cr.cid) + return nil, fmt.Errorf("cluster ID mismatch") default: resp.Body.Close() return nil, fmt.Errorf("unhandled http status %d", resp.StatusCode)