Compare commits

...

51 Commits

Author SHA1 Message Date
9fa3bea5a2 *: bump to v0.4.9 2015-03-31 13:54:58 -07:00
2fc8304300 Merge pull request #2586 from xiang90/047snap
server: introduce /v2/migration/snapshot endpoint
2015-03-27 17:42:19 -07:00
087ba30a90 server: introduce /v2/migration/snapshot endpoint 2015-03-27 17:42:06 -07:00
e1df265dc5 Merge pull request #2595 from yichengq/revert-upgrade-related
Revert upgrade related commits
2015-03-27 16:23:40 -07:00
8059598332 Revert "server: add version monitoring"
This reverts commit 4f1f003d04.
2015-03-27 16:09:11 -07:00
e1e2daa205 Revert "etcd: register usable versions when bootstrap"
This reverts commit 9f70568a02.
2015-03-27 16:09:04 -07:00
399931cec9 Revert "next-version-handler"
This reverts commit f36d55f062.
2015-03-27 16:08:54 -07:00
49715173cb Revert "server: add internal version"
This reverts commit 9a2d82854e.

Conflicts:
	server/version.go
2015-03-27 16:06:31 -07:00
ad4f231b40 Revert "server: standby exits when detecting v2 is running"
This reverts commit ebb8d781b5.
2015-03-27 16:04:40 -07:00
55263bc6b5 Revert "etcd: add -internal-dir flag"
This reverts commit 03a99cf9b1.
2015-03-27 16:03:49 -07:00
262d769168 *: bump to v0.4.8+git 2015-03-23 14:20:09 -07:00
2f6ea0a0e5 *: bump to v0.4.8 2015-03-23 13:47:10 -07:00
fc8020b7d6 Merge pull request #2546 from kelseyhightower/add-internal-dir-flag
etcd: add -internal-dir flag
2015-03-20 10:36:36 -07:00
03a99cf9b1 etcd: add -internal-dir flag
etcd supports setting the path to the etcd binary directory used for
running legacy mode and upgrades.

etcd no longer limits internal version checking to GOOS=linux.
2015-03-19 20:01:47 -07:00
eae1e18500 Merge pull request #2418 from kelseyhightower/release-0.4
Documentation: make -bind-addr and -peer-bind-addr docs match the code
2015-03-11 15:35:08 -07:00
6666b20d91 Documentation: make -bind-addr and -peer-bind-addr docs match the code
Fixes #2072.
2015-03-11 15:31:38 -07:00
2d4592e8c5 Merge pull request #2416 from aeneby/etcd_trace_fix
config: Capitalise strTrace field name
2015-03-03 21:05:23 -08:00
12fec1f936 config: Capitalise strTrace field name
Field names not beginning with a capital letter will not be exported
and therefore cannot be assigned values. This breaks the usage of
ETCD_TRACE when debugging.

Fixes #1970
2015-03-03 14:52:08 +01:00
d6523fe463 bump to v0.4.7 2015-02-10 15:59:33 -08:00
c25127a699 Merge pull request #2262 from yichengq/047
server: forbid /v2/stats/leader on follower
2015-02-09 22:29:48 -08:00
9f031e6218 server: forbid /v2/stats/leader on follower 2015-02-09 14:50:34 -08:00
e55724e959 Merge pull request #2260 from yichengq/047
server: refresh commit index when someone rejoins
2015-02-09 14:35:00 -08:00
29af192e3d server: refresh commit index when someone rejoins
Update commit index when rejoin happens, because 2.0 doesn't accept
more than one uncommitted config entry.
2015-02-09 14:28:30 -08:00
2fc79912c2 Merge pull request #2194 from yichengq/o3
server: standby exits when detecting v2 is running
2015-01-30 09:32:19 -08:00
ebb8d781b5 server: standby exits when detecting v2 is running 2015-01-29 16:26:47 -08:00
2e30b3c17f Merge pull request #2130 from xiang90/047-version
server: add internal version
2015-01-22 15:23:38 -08:00
9a2d82854e server: add internal version 2015-01-22 15:23:15 -08:00
b077dcf6c4 Merge pull request #2125 from xiang90/047-handler
next-version-handler
2015-01-22 11:40:54 -08:00
2b572cb6e8 Merge pull request #2126 from yichengq/o1
etcd: register usable versions when bootstrap
2015-01-22 11:32:23 -08:00
f36d55f062 next-version-handler 2015-01-22 11:20:52 -08:00
9f70568a02 etcd: register usable versions when bootstrap 2015-01-22 11:08:58 -08:00
1ca7d1e064 Merge pull request #2124 from xiang90/047-version
server: add version monitoring
2015-01-22 10:38:27 -08:00
4f1f003d04 server: add version monitoring 2015-01-22 10:23:15 -08:00
49e0dff2b8 CHANGELOG: v0.4.6 2014-07-29 10:31:48 -07:00
686837227e fix(docs/api): mention version endpoint is per instance 2014-07-28 11:28:16 -07:00
f2652f005e Merge pull request #882 from cap10morgan/patch-1
add the /version endpoint to the API docs
2014-07-28 11:26:24 -07:00
5490eb5406 Merge pull request #907 from MattParker89/patch-1
Adds units of time to flag docs
2014-07-27 22:37:42 -07:00
70dda950ed Adds units of time to flag docs
This fixes issue #905 based on the comments provided in server/cluster_config.go
2014-07-27 00:39:02 -04:00
a884f2a18a Merge pull request #881 from unihorn/111
standby server: save Running info correctly
2014-07-24 17:29:25 -07:00
bdeb96be0f Merge pull request #900 from unihorn/fix-timer
server: fix timer leak
2014-07-21 16:37:04 -07:00
c00594e680 server: fix timer leak 2014-07-21 14:23:52 -07:00
919cd380ec Merge pull request #883 from philips/add-consistent-note
Documentation: add note about consistent=true
2014-07-14 14:39:38 -08:00
b83aec6b87 Merge pull request #889 from robszumski/uuid
fix(docs): name defaults to uuid not hostname
2014-07-14 14:13:55 -07:00
05bfb369ef Documentation: add note about consistent=true 2014-07-13 11:07:59 -08:00
0639c4c86d fix(docs): name defaults to uuid not hostname 2014-07-11 11:30:05 -07:00
877b3d51bb Merge pull request #886 from christriddle/master
Added Access-Control-Allow-Headers for CORS requests
2014-07-10 13:05:07 -07:00
d9df58beb8 Added Access-Control-Allow-Headers to allow cors requests with those headers 2014-07-10 17:02:41 +01:00
1cffdb3a48 Merge pull request #866 from coreos/qread
feat(get): get from quorum
2014-07-08 18:30:18 -07:00
0593a52107 add the /version endpoint to the API docs
I had to find this by accident. It should be documented here.
2014-07-08 17:26:47 -04:00
f7854c4ab9 standby server: save Running info correctly
Running should be true when Start, and set to false when switching to
the other mode.
2014-07-08 08:29:17 -07:00
973bde9a07 feat(get): get from quorum 2014-06-22 21:33:38 -07:00
15 changed files with 157 additions and 37 deletions

View File

@ -1,3 +1,10 @@
v0.4.6
* Fix long-term timer leak (#900, #875, #868, #904)
* Fix `Running` field in standby_info file (#881)
* Add `quorum=true` query parameter for GET requests (#866, #883)
* Add `Access-Control-Allow-Headers` header for CORS requests (#886)
* Various documentation improvements (#907, #882)
v0.4.5
* Flush headers immediatly on `wait=true` requests (#877)
* Add `ETCD_HTTP_READ_TIMEOUT` and `ETCD_HTTP_WRITE_TIMEOUT` (#880)

View File

@ -13,6 +13,14 @@ This will bring up etcd listening on default ports (4001 for client communicatio
The `-data-dir machine0` argument tells etcd to write machine configuration, logs and snapshots to the `./machine0/` directory.
The `-name machine0` tells the rest of the cluster that this machine is named machine0.
## Getting the etcd version
The etcd version of a specific instance can be obtained from the `/version` endpoint.
```sh
curl -L http://127.0.0.1:4001/version
```
## Key Space Operations
The primary API of etcd is a hierarchical key space.
@ -833,6 +841,8 @@ curl -L http://127.0.0.1:4001/v2/keys/afile -XPUT --data-urlencode value@afile.t
### Read Consistency
#### Read from the Master
Followers in a cluster can be behind the leader in their copy of the keyspace.
If your application wants or needs the most up-to-date version of a key then it should ensure it reads from the current leader.
By using the `consistent=true` flag in your GET requests, etcd will make sure you are talking to the current master.
@ -843,6 +853,19 @@ The client is told the write was successful and the keyspace is updated.
Meanwhile F2 has partitioned from the network and will have an out-of-date version of the keyspace until the partition resolves.
Since F2 missed the most recent write, a client reading from F2 will have an out-of-date version of the keyspace.
Implementation notes on `consistent=true`: If the leader you are talking to is
partitioned it will be unable to determine if it is not currently the master.
In a later version we will provide a mechanism to set an upperbound of time
that the current master can be unable to contact the quorom and still serve
reads.
### Read Linearization
If you want a read that is fully linearized you can use a `quorum=true` GET.
The read will take a very similar path to a write and will have a similar
speed. If you are unsure if you need this feature feel free to email etcd-dev
for advice.
## Lock Module (*Deprecated and Removed*)
The lock module is used to serialize access to resources used by clients.

View File

@ -26,7 +26,7 @@ The full documentation is contained in the [API docs](https://github.com/coreos/
### Required
* `-name` - The node name. Defaults to the hostname.
* `-name` - The node name. Defaults to a UUID.
### Optional
@ -34,7 +34,7 @@ The full documentation is contained in the [API docs](https://github.com/coreos/
* `-discovery` - A URL to use for discovering the peer list. (i.e `"https://discovery.etcd.io/your-unique-key"`).
* `-http-read-timeout` - The number of seconds before an HTTP read operation is timed out.
* `-http-write-timeout` - The number of seconds before an HTTP write operation is timed out.
* `-bind-addr` - The listening hostname for client communication. Defaults to advertised IP.
* `-bind-addr` - The listening hostname for client communication. Defaults to 0.0.0.0 and the advertised port.
* `-peers` - A comma separated list of peers in the cluster (i.e `"203.0.113.101:7001,203.0.113.102:7001"`).
* `-peers-file` - The file path containing a comma separated list of peers in the cluster.
* `-ca-file` - The path of the client CAFile. Enables client cert authentication when present.
@ -47,7 +47,7 @@ The full documentation is contained in the [API docs](https://github.com/coreos/
* `-max-result-buffer` - The max size of result buffer. Defaults to `1024`.
* `-max-retry-attempts` - The max retry attempts when trying to join a cluster. Defaults to `3`.
* `-peer-addr` - The advertised public hostname:port for server communication. Defaults to `127.0.0.1:7001`.
* `-peer-bind-addr` - The listening hostname for server communication. Defaults to advertised IP.
* `-peer-bind-addr` - The listening hostname for server communication. Defaults to 0.0.0.0 and the advertised peer port.
* `-peer-ca-file` - The path of the CAFile. Enables client/peer cert authentication when present.
* `-peer-cert-file` - The cert file of the server.
* `-peer-key-file` - The key file of the server.
@ -55,8 +55,8 @@ The full documentation is contained in the [API docs](https://github.com/coreos/
* `-peer-heartbeat-interval` - The number of milliseconds in between heartbeat requests
* `-snapshot=false` - Disable log snapshots. Defaults to `true`.
* `-cluster-active-size` - The expected number of instances participating in the consensus protocol. Only applied if the etcd instance is the first peer in the cluster.
* `-cluster-remove-delay` - The delay before one node is removed from the cluster since it cannot be connected at all. Only applied if the etcd instance is the first peer in the cluster.
* `-cluster-sync-interval` - The interval between synchronization for standby-mode instance with the cluster. Only applied if the etcd instance is the first peer in the cluster.
* `-cluster-remove-delay` - The number of seconds before one node is removed from the cluster since it cannot be connected at all. Only applied if the etcd instance is the first peer in the cluster.
* `-cluster-sync-interval` - The number of seconds between synchronization for standby-mode instance with the cluster. Only applied if the etcd instance is the first peer in the cluster.
* `-v` - Enable verbose logging. Defaults to `false`.
* `-vv` - Enable very verbose logging. Defaults to `false`.
* `-version` - Print the version and exit.

View File

@ -1,6 +1,6 @@
# etcd
README version 0.4.5
README version 0.4.8
A highly-available key value store for shared configuration and service discovery.
etcd is inspired by [Apache ZooKeeper][zookeeper] and [doozer][doozer], with a focus on being:

View File

@ -86,7 +86,7 @@ type Config struct {
HeartbeatInterval int `toml:"heartbeat_interval" env:"ETCD_PEER_HEARTBEAT_INTERVAL"`
ElectionTimeout int `toml:"election_timeout" env:"ETCD_PEER_ELECTION_TIMEOUT"`
}
strTrace string `toml:"trace" env:"ETCD_TRACE"`
StrTrace string `toml:"trace" env:"ETCD_TRACE"`
GraphiteHost string `toml:"graphite_host" env:"ETCD_GRAPHITE_HOST"`
Cluster struct {
ActiveSize int `toml:"active_size" env:"ETCD_CLUSTER_ACTIVE_SIZE"`
@ -275,7 +275,7 @@ func (c *Config) LoadFlags(arguments []string) error {
f.IntVar(&c.SnapshotCount, "snapshot-count", c.SnapshotCount, "")
f.StringVar(&c.CPUProfileFile, "cpuprofile", "", "")
f.StringVar(&c.strTrace, "trace", "", "")
f.StringVar(&c.StrTrace, "trace", "", "")
f.StringVar(&c.GraphiteHost, "graphite-host", "", "")
f.IntVar(&c.Cluster.ActiveSize, "cluster-active-size", c.Cluster.ActiveSize, "")
@ -441,7 +441,7 @@ func (c *Config) MetricsBucketName() string {
// Trace determines if any trace-level information should be emitted
func (c *Config) Trace() bool {
return c.strTrace == "*"
return c.StrTrace == "*"
}
func (c *Config) ClusterConfig() *server.ClusterConfig {

View File

@ -54,6 +54,7 @@ type CORSHandler struct {
func (h *CORSHandler) addHeader(w http.ResponseWriter, origin string) {
w.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Add("Access-Control-Allow-Origin", origin)
w.Header().Add("Access-Control-Allow-Headers", "accept, content-type")
}
// ServeHTTP adds the correct CORS headers based on the origin and returns immediately

View File

@ -46,6 +46,7 @@ func (c *JoinCommand) NodeName() string {
// applyJoin attempts to join a machine to the cluster.
func applyJoin(c *JoinCommand, context raft.Context) (uint64, error) {
ps, _ := context.Server().Context().(*PeerServer)
ps.raftServer.FlushCommitIndex()
commitIndex := context.CommitIndex()
// Make sure we're not getting a cached value from the registry.

View File

@ -772,9 +772,9 @@ func (s *PeerServer) startRoutine(f func()) {
func (s *PeerServer) monitorSnapshot() {
for {
timer := time.NewTimer(s.snapConf.checkingInterval)
defer timer.Stop()
select {
case <-s.closeChan:
timer.Stop()
return
case <-timer.C:
}
@ -807,6 +807,8 @@ func (s *PeerServer) monitorSync() {
// monitorTimeoutThreshold groups timeout threshold events together and prints
// them as a single log line.
func (s *PeerServer) monitorTimeoutThreshold() {
ticker := time.NewTicker(ThresholdMonitorTimeout)
defer ticker.Stop()
for {
select {
case <-s.closeChan:
@ -815,12 +817,10 @@ func (s *PeerServer) monitorTimeoutThreshold() {
log.Infof("%s: warning: heartbeat near election timeout: %v", s.Config.Name, value)
}
timer := time.NewTimer(ThresholdMonitorTimeout)
defer timer.Stop()
select {
case <-s.closeChan:
return
case <-timer.C:
case <-ticker.C:
}
}
}
@ -828,13 +828,13 @@ func (s *PeerServer) monitorTimeoutThreshold() {
// monitorActiveSize has the leader periodically check the status of cluster
// nodes and swaps them out for standbys as needed.
func (s *PeerServer) monitorActiveSize() {
ticker := time.NewTicker(ActiveMonitorTimeout)
defer ticker.Stop()
for {
timer := time.NewTimer(ActiveMonitorTimeout)
defer timer.Stop()
select {
case <-s.closeChan:
return
case <-timer.C:
case <-ticker.C:
}
// Ignore while this peer is not a leader.
@ -864,13 +864,13 @@ func (s *PeerServer) monitorActiveSize() {
// monitorPeerActivity has the leader periodically for dead nodes and demotes them.
func (s *PeerServer) monitorPeerActivity() {
ticker := time.NewTicker(PeerActivityMonitorTimeout)
defer ticker.Stop()
for {
timer := time.NewTimer(PeerActivityMonitorTimeout)
defer timer.Stop()
select {
case <-s.closeChan:
return
case <-timer.C:
case <-ticker.C:
}
// Ignore while this peer is not a leader.

View File

@ -1,3 +1,3 @@
package server
const ReleaseVersion = "0.4.5"
const ReleaseVersion = "0.4.9"

View File

@ -3,8 +3,10 @@ package server
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/pprof"
"path"
"strings"
"time"
@ -135,6 +137,7 @@ func (s *Server) installV2(r *mux.Router) {
s.handleFunc(r2, "/v2/stats/leader", s.GetLeaderStatsHandler).Methods("GET", "HEAD")
s.handleFunc(r2, "/v2/stats/store", s.GetStoreStatsHandler).Methods("GET", "HEAD")
s.handleFunc(r2, "/v2/speedTest", s.SpeedTestHandler).Methods("GET", "HEAD")
s.handleFunc(r2, "/v2/migration/snapshot", s.SnapshotHandler).Methods("GET")
}
func (s *Server) installMod(r *mux.Router) {
@ -324,12 +327,8 @@ func (s *Server) GetLeaderStatsHandler(w http.ResponseWriter, req *http.Request)
return nil
}
leader := s.peerServer.RaftServer().Leader()
if leader == "" {
return etcdErr.NewError(300, "", s.Store().Index())
}
hostname, _ := s.registry.ClientURL(leader)
uhttp.Redirect(hostname, w, req)
w.WriteHeader(http.StatusForbidden)
w.Write([]byte("not current leader"))
return nil
}
@ -363,6 +362,41 @@ func (s *Server) SpeedTestHandler(w http.ResponseWriter, req *http.Request) erro
return nil
}
// SnapshotHandler forces etcd store to do a snapshot. If the disk parameter is set, the snapshot
// will be written to disk at data-dir/index-migrate.snap. Or the snapshot will be returned as
// http body.
func (s *Server) SnapshotHandler(w http.ResponseWriter, req *http.Request) error {
data, err := s.Store().Save()
if err != nil {
http.Error(w, "failed to create snapshot: "+err.Error(), http.StatusInternalServerError)
log.Warn("Failed to create snapshot:" + err.Error())
return nil
}
disk := req.FormValue("disk")
if disk == "true" {
name := fmt.Sprintf("%d-migrate.snap", s.peerServer.RaftServer().CommitIndex())
err = ioutil.WriteFile(path.Join(s.peerServer.RaftServer().Path(), name), data, 0600)
if err != nil {
http.Error(w, "failed to save snapshot: "+err.Error(), http.StatusInternalServerError)
log.Warn("server: failed to save snapshot: " + err.Error())
return nil
}
log.Infof("server: saved snapshot file %s successfully", name)
return nil
}
if disk != "" && disk != "false" {
http.Error(w, "invalid parameter: disk="+disk, http.StatusBadRequest)
return nil
}
_, err = w.Write(data)
if err != nil {
log.Warnf("server: failed to write snapshot to %s: %v", req.RemoteAddr, err.Error())
}
return nil
}
// Retrieves metrics from bucket
func (s *Server) GetMetricsHandler(w http.ResponseWriter, req *http.Request) error {
(*s.metrics).Dump(w)

View File

@ -30,6 +30,7 @@ type StandbyServerConfig struct {
}
type standbyInfo struct {
// stay running in standby mode
Running bool
Cluster []*machineMessage
SyncInterval float64
@ -78,12 +79,16 @@ func (s *StandbyServer) Start() {
s.removeNotify = make(chan bool)
s.closeChan = make(chan bool)
s.Running = true
if err := s.saveInfo(); err != nil {
log.Warnf("error saving cluster info for standby")
}
s.routineGroup.Add(1)
go func() {
defer s.routineGroup.Done()
s.monitorCluster()
}()
s.Running = true
}
// Stop stops the server gracefully.
@ -97,11 +102,6 @@ func (s *StandbyServer) Stop() {
close(s.closeChan)
s.routineGroup.Wait()
if err := s.saveInfo(); err != nil {
log.Warnf("error saving cluster info for standby")
}
s.Running = false
}
// RemoveNotify notifies the server is removed from standby mode and ready
@ -178,13 +178,13 @@ func (s *StandbyServer) redirectRequests(w http.ResponseWriter, r *http.Request)
// monitorCluster assumes that the machine has tried to join the cluster and
// failed, so it waits for the interval at the beginning.
func (s *StandbyServer) monitorCluster() {
ticker := time.NewTicker(time.Duration(int64(s.SyncInterval * float64(time.Second))))
defer ticker.Stop()
for {
timer := time.NewTimer(time.Duration(int64(s.SyncInterval * float64(time.Second))))
defer timer.Stop()
select {
case <-s.closeChan:
return
case <-timer.C:
case <-ticker.C:
}
if err := s.syncCluster(nil); err != nil {
@ -204,6 +204,10 @@ func (s *StandbyServer) monitorCluster() {
}
log.Infof("join through leader %v", leader.PeerURL)
s.Running = false
if err := s.saveInfo(); err != nil {
log.Warnf("error saving cluster info for standby")
}
go func() {
s.Stop()
close(s.removeNotify)

View File

@ -17,6 +17,14 @@ func GetHandler(w http.ResponseWriter, req *http.Request, s Server) error {
vars := mux.Vars(req)
key := "/" + vars["key"]
recursive := (req.FormValue("recursive") == "true")
sort := (req.FormValue("sorted") == "true")
if req.FormValue("quorum") == "true" {
c := s.Store().CommandFactory().CreateGetCommand(key, recursive, sort)
return s.Dispatch(c, w, req)
}
// Help client to redirect the request to the current leader
if req.FormValue("consistent") == "true" && s.State() != raft.Leader {
leader := s.Leader()
@ -35,8 +43,6 @@ func GetHandler(w http.ResponseWriter, req *http.Request, s Server) error {
return nil
}
recursive := (req.FormValue("recursive") == "true")
sort := (req.FormValue("sorted") == "true")
waitIndex := req.FormValue("waitIndex")
stream := (req.FormValue("stream") == "true")

View File

@ -24,6 +24,7 @@ type CommandFactory interface {
prevIndex uint64, expireTime time.Time) raft.Command
CreateCompareAndDeleteCommand(key string, prevValue string, prevIndex uint64) raft.Command
CreateSyncCommand(now time.Time) raft.Command
CreateGetCommand(key string, recursive, sorted bool) raft.Command
}
// RegisterCommandFactory adds a command factory to the global registry.

View File

@ -89,3 +89,11 @@ func (f *CommandFactory) CreateSyncCommand(now time.Time) raft.Command {
Time: time.Now(),
}
}
func (f *CommandFactory) CreateGetCommand(key string, recursive, sorted bool) raft.Command {
return &GetCommand{
Key: key,
Recursive: recursive,
Sorted: sorted,
}
}

35
store/v2/get_command.go Normal file
View File

@ -0,0 +1,35 @@
package v2
import (
"github.com/coreos/etcd/log"
"github.com/coreos/etcd/store"
"github.com/coreos/etcd/third_party/github.com/goraft/raft"
)
func init() {
raft.RegisterCommand(&GetCommand{})
}
// The GetCommand gets a key from the Store.
type GetCommand struct {
Key string `json:"key"`
Recursive bool `json:"recursive"`
Sorted bool `json:sorted`
}
// The name of the get command in the log
func (c *GetCommand) CommandName() string {
return "etcd:get"
}
// Get the key
func (c *GetCommand) Apply(context raft.Context) (interface{}, error) {
s, _ := context.Server().StateMachine().(store.Store)
e, err := s.Get(c.Key, c.Recursive, c.Sorted)
if err != nil {
log.Debug(err)
return nil, err
}
return e, nil
}