Skip to content

Commit 077dc12

Browse files
authored
Merge pull request #88 from arangodb-helper/resilientsingle
Resilient single server support
2 parents fa45c04 + 20d7742 commit 077dc12

33 files changed

+640
-76
lines changed

.travis.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ services:
66
language: go
77

88
env:
9-
- TEST_SUITE=run-tests-local-process ARANGODB=arangodb:3.1
10-
- TEST_SUITE=run-tests-docker ARANGODB=arangodb:3.1
11-
- TEST_SUITE=run-tests-local-process ARANGODB=arangodb/arangodb:latest
12-
- TEST_SUITE=run-tests-docker ARANGODB=arangodb/arangodb:latest
13-
- TEST_SUITE=run-tests-local-process ARANGODB=arangodb/arangodb-preview:latest
14-
- TEST_SUITE=run-tests-docker ARANGODB=arangodb/arangodb-preview:latest
9+
- TEST_SUITE=run-tests-local-process ARANGODB=arangodb:3.1 STARTER_MODES="single,cluster"
10+
- TEST_SUITE=run-tests-docker ARANGODB=arangodb:3.1 STARTER_MODES="single,cluster"
11+
- TEST_SUITE=run-tests-local-process ARANGODB=arangodb/arangodb:latest STARTER_MODES="single,cluster"
12+
- TEST_SUITE=run-tests-docker ARANGODB=arangodb/arangodb:latest STARTER_MODES="single,cluster"
13+
- TEST_SUITE=run-tests-local-process ARANGODB=arangodb/arangodb-preview:latest STARTER_MODES="single,cluster,resilientsingle"
14+
- TEST_SUITE=run-tests-docker ARANGODB=arangodb/arangodb-preview:latest STARTER_MODES="single,cluster,resilientsingle"
1515

1616
script: make $TEST_SUITE
1717

.vscode/settings.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
// Place your settings in this file to overwrite default and user settings.
22
{
33
"go.testFlags": ["-v"],
4-
"go.testTimeout": "600s"
4+
"go.testTimeout": "600s",
5+
"search.exclude": {
6+
"**/node_modules": true,
7+
"**/bower_components": true,
8+
"vendor": true
9+
}
510
}

Makefile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ REPODIR := $(ORGDIR)/$(REPONAME)
1919
REPOPATH := $(ORGPATH)/$(REPONAME)
2020

2121
GOPATH := $(GOBUILDDIR)
22-
GOVERSION := 1.9.0-alpine
22+
GOVERSION := 1.9.1-alpine
2323

2424
ifndef GOOS
2525
GOOS := linux
@@ -156,15 +156,16 @@ run-tests-local-process: build test-images
156156
-e DATA_DIR=/tmp \
157157
-e STARTER=/usr/code/bin/linux/amd64/arangodb \
158158
-e TEST_MODES=localprocess \
159+
-e STARTER_MODES=$(STARTER_MODES) \
159160
-e TESTOPTIONS=$(TESTOPTIONS) \
160161
-e DEBUG_CLUSTER=$(DEBUG_CLUSTER) \
161162
-w /usr/code/ \
162163
arangodb-golang \
163164
go test -timeout $(TEST_TIMEOUT) $(TESTOPTIONS) -v $(REPOPATH)/test
164165

165166
run-tests-docker: docker
166-
GOPATH=$(GOBUILDDIR) TEST_MODES=docker IP=$(IP) ARANGODB=$(ARANGODB) go test -timeout $(TEST_TIMEOUT) $(TESTOPTIONS) -v $(REPOPATH)/test
167+
GOPATH=$(GOBUILDDIR) TEST_MODES=docker STARTER_MODES=$(STARTER_MODES) IP=$(IP) ARANGODB=$(ARANGODB) go test -timeout $(TEST_TIMEOUT) $(TESTOPTIONS) -v $(REPOPATH)/test
167168

168169
# Run all integration tests on the local system
169170
run-tests-local: local
170-
GOPATH=$(GOBUILDDIR) TEST_MODES="localprocess docker" STARTER=$(ROOTDIR)/arangodb go test -timeout $(TEST_TIMEOUT) $(TESTOPTIONS) -v $(REPOPATH)/test
171+
GOPATH=$(GOBUILDDIR) TEST_MODES="localprocess,docker" STARTER_MODES=$(STARTER_MODES) STARTER=$(ROOTDIR)/arangodb go test -timeout $(TEST_TIMEOUT) $(TESTOPTIONS) -v $(REPOPATH)/test

README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,62 @@ docker run -it --name=adb --rm -p 8528:8528 \
194194
--starter.mode=single
195195
```
196196

197+
Starting a resilient single server pair
198+
---------------------------------------
199+
200+
If you want to start a resilient single database server, use `--starter.mode=resilientsingle`.
201+
In this mode a 3 machine agency is started and 2 single servers that perform
202+
asynchronous replication an failover if needed.
203+
204+
```
205+
arangodb --starter.mode=resilientsingle --starter.join A,B,C
206+
```
207+
208+
Run this on machine A, B & C.
209+
210+
The starter will decide on which 2 machines to run a single server instance.
211+
To override this decision (only valid while bootstrapping), add a
212+
`--cluster.start-single=false` to the machine where the single server
213+
instance should NOT be scheduled.
214+
215+
Starting a resilient single server pair in Docker
216+
-------------------------------------------------
217+
218+
If you want to start a resilient single database server running in docker containers,
219+
use the normal docker arguments, combined with `--starter.mode=resilientsingle`.
220+
221+
```
222+
export IP=<IP of docker host>
223+
docker volume create arangodb
224+
docker run -it --name=adb --rm -p 8528:8528 \
225+
-v arangodb:/data \
226+
-v /var/run/docker.sock:/var/run/docker.sock \
227+
arangodb/arangodb-starter \
228+
--starter.address=$IP \
229+
--starter.mode=resilientsingle \
230+
--starter.join=A,B,C
231+
```
232+
233+
Run this on machine A, B & C.
234+
235+
The starter will decide on which 2 machines to run a single server instance.
236+
To override this decision (only valid while bootstrapping), add a
237+
`--cluster.start-single=false` to the machine where the single server
238+
instance should NOT be scheduled.
239+
240+
Starting a local test resilient single sever pair
241+
-------------------------------------------------
242+
243+
If you want to start a local resilient server pair quickly, use the `--starter.local` flag.
244+
It will start all servers within the context of a single starter process.
245+
246+
```
247+
arangodb --starter.local --starter.mode=resilientsingle
248+
```
249+
250+
Note: When you restart the started, it remembers the original `--starter.local` flag.
251+
252+
197253
Starting & stopping in detached mode
198254
------------------------------------
199255

main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ var (
7979
startAgent []bool
8080
startDBserver []bool
8181
startCoordinator []bool
82+
startResilientSingle []bool
8283
startLocalSlaves bool
8384
mode string
8485
dataDir string
@@ -121,7 +122,7 @@ func init() {
121122
f.BoolVar(&showVersion, "version", false, "If set, show version and exit")
122123

123124
f.StringSliceVar(&masterAddresses, "starter.join", nil, "join a cluster with master at given address")
124-
f.StringVar(&mode, "starter.mode", "cluster", "Set the mode of operation to use (cluster|single)")
125+
f.StringVar(&mode, "starter.mode", "cluster", "Set the mode of operation to use (cluster|single|resilientsingle)")
125126
f.BoolVar(&startLocalSlaves, "starter.local", false, "If set, local slaves will be started to create a machine local (test) cluster")
126127
f.StringVar(&ownAddress, "starter.address", "", "address under which this server is reachable, needed for running in docker or in single mode")
127128
f.StringVar(&id, "starter.id", "", "Unique identifier of this peer")
@@ -137,6 +138,7 @@ func init() {
137138
f.BoolSliceVar(&startAgent, "cluster.start-agent", nil, "should an agent instance be started")
138139
f.BoolSliceVar(&startDBserver, "cluster.start-dbserver", nil, "should a dbserver instance be started")
139140
f.BoolSliceVar(&startCoordinator, "cluster.start-coordinator", nil, "should a coordinator instance be started")
141+
f.BoolSliceVar(&startResilientSingle, "cluster.start-single", nil, "should a (resilient) single server instance be started")
140142

141143
f.StringVar(&arangodPath, "server.arangod", "/usr/sbin/arangod", "Path of arangod")
142144
f.StringVar(&arangodJSPath, "server.js-dir", "/usr/share/arangodb3/js", "Path of arango JS folder")
@@ -504,6 +506,7 @@ func mustPrepareService(generateAutoKeyFile bool) (*service.Service, service.Boo
504506
StartAgent: getOptionalBool("cluster.start-agent", startAgent),
505507
StartDBserver: getOptionalBool("cluster.start-dbserver", startDBserver),
506508
StartCoordinator: getOptionalBool("cluster.start-coordinator", startCoordinator),
509+
StartResilientSingle: getOptionalBool("cluster.start-single", startResilientSingle),
507510
ServerStorageEngine: serverStorageEngine,
508511
JwtSecret: jwtSecret,
509512
SslKeyFile: sslKeyFile,

service/arangod_config_builder.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func createArangodConf(log *logging.Logger, bsCfg BootstrapConfig, myHostDir, my
8080
case ServerTypeDBServer:
8181
threads = "4"
8282
v8Contexts = "4"
83-
case ServerTypeCoordinator, ServerTypeSingle:
83+
case ServerTypeCoordinator, ServerTypeSingle, ServerTypeResilientSingle:
8484
threads = "16"
8585
v8Contexts = "4"
8686
}
@@ -246,6 +246,14 @@ func createArangodArgs(log *logging.Logger, config Config, clusterConfig Cluster
246246
optionPair{"--foxx.queues", "true"},
247247
optionPair{"--server.statistics", "true"},
248248
)
249+
case ServerTypeResilientSingle:
250+
options = append(options,
251+
optionPair{"--foxx.queues", "true"},
252+
optionPair{"--server.statistics", "true"},
253+
optionPair{"--replication.automatic-failover", "true"},
254+
optionPair{"--cluster.my-address", myTCPURL},
255+
optionPair{"--cluster.my-role", "SINGLE"},
256+
)
249257
}
250258
if serverType != ServerTypeAgent && serverType != ServerTypeSingle {
251259
for _, p := range clusterConfig.AllAgents() {

service/bootstrap_config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type BootstrapConfig struct {
3434
StartAgent *bool // If not nil, sets if starter starts a agent, otherwise default handling applies
3535
StartDBserver *bool // If not nil, sets if starter starts a dbserver, otherwise default handling applies
3636
StartCoordinator *bool // If not nil, sets if starter starts a coordinator, otherwise default handling applies
37+
StartResilientSingle *bool // If not nil, sets if starter starts a resilient single, otherwise default handling applies
3738
ServerStorageEngine string // mmfiles | rocksdb
3839
JwtSecret string // JWT secret used for arangod communication
3940
SslKeyFile string // Path containing an x509 certificate + private key to be used by the servers.

service/bootstrap_master.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ func (s *Service) bootstrapMaster(ctx context.Context, runner Runner, config Con
4949
hasAgent := boolFromRef(bsCfg.StartAgent, !s.mode.IsSingleMode())
5050
hasDBServer := boolFromRef(bsCfg.StartDBserver, true)
5151
hasCoordinator := boolFromRef(bsCfg.StartCoordinator, true)
52+
hasResilientSingle := boolFromRef(bsCfg.StartResilientSingle, s.mode.IsResilientSingleMode())
5253
s.myPeers.Initialize(
53-
NewPeer(s.id, config.OwnAddress, s.announcePort, 0, config.DataDir, hasAgent, hasDBServer, hasCoordinator, s.IsSecure()),
54+
NewPeer(s.id, config.OwnAddress, s.announcePort, 0, config.DataDir, hasAgent, hasDBServer, hasCoordinator, hasResilientSingle, s.IsSecure()),
5455
bsCfg.AgencySize)
5556
s.learnOwnAddress = config.OwnAddress == ""
5657

service/bootstrap_slave.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,15 @@ func (s *Service) bootstrapSlave(peerAddress string, runner Runner, config Confi
4242
s.log.Fatalf("Failed to get HTTP server port: %#v", err)
4343
}
4444
encoded, err := json.Marshal(HelloRequest{
45-
DataDir: config.DataDir,
46-
SlaveID: s.id,
47-
SlaveAddress: config.OwnAddress,
48-
SlavePort: hostPort,
49-
IsSecure: s.IsSecure(),
50-
Agent: copyBoolRef(bsCfg.StartAgent),
51-
DBServer: copyBoolRef(bsCfg.StartDBserver),
52-
Coordinator: copyBoolRef(bsCfg.StartCoordinator),
45+
DataDir: config.DataDir,
46+
SlaveID: s.id,
47+
SlaveAddress: config.OwnAddress,
48+
SlavePort: hostPort,
49+
IsSecure: s.IsSecure(),
50+
Agent: copyBoolRef(bsCfg.StartAgent),
51+
DBServer: copyBoolRef(bsCfg.StartDBserver),
52+
Coordinator: copyBoolRef(bsCfg.StartCoordinator),
53+
ResilientSingle: copyBoolRef(bsCfg.StartResilientSingle),
5354
})
5455
if err != nil {
5556
s.log.Fatalf("Failed to encode Hello request: %#v", err)

service/cluster_config.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,18 @@ func (p ClusterConfig) HaveEnoughAgents() bool {
154154
return count >= p.AgencySize
155155
}
156156

157+
// HaveEnoughResilientSingles returns true when the number of peers that have an resilient single server
158+
// is equal to 2.
159+
func (p ClusterConfig) HaveEnoughResilientSingles() bool {
160+
count := 0
161+
for _, x := range p.AllPeers {
162+
if x.HasResilientSingle() {
163+
count++
164+
}
165+
}
166+
return count >= 2
167+
}
168+
157169
// IsSecure returns true if any of the peers is secure.
158170
func (p ClusterConfig) IsSecure() bool {
159171
for _, x := range p.AllPeers {

0 commit comments

Comments
 (0)