Skip to content

Commit d5f5de6

Browse files
committed
Resolve and re-set BindAddr to propagate an unique IP address
1 parent 18f3c0c commit d5f5de6

File tree

9 files changed

+241
-280
lines changed

9 files changed

+241
-280
lines changed

README.md

Lines changed: 27 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ Olric is in early stages of development. The package API and client protocol may
7676
* [Serialization](#serialization)
7777
* [Golang Client](#golang-client)
7878
* [Configuration](#configuration)
79+
* [Embedded Member Mode](#embedded-member-mode)
80+
* [Client-Server Mode](#client-server-mode)
81+
* [Network Configuration](#network-configuration)
7982
* [Service discovery](#service-discovery)
8083
* [Architecture](#architecture)
8184
* [Overview](#overview)
@@ -807,152 +810,42 @@ configuration parameters, see [Olric documentation on GoDoc.org](https://godoc.o
807810

808811
## Configuration
809812

810-
[memberlist configuration](https://godoc.org/github.com/hashicorp/memberlist#Config) can be tricky and the default configuration set should be tuned for your environment. A detailed deployment and configuration guide will be prepared before stable release.
813+
You should feel free to ask any questions about configuration and integration. Please see [Support](#support) section.
811814

812-
Please take a look at [Config section at godoc.org](https://godoc.org/github.com/buraksezer/olric#Config)
815+
### Embedded-Member Mode
813816

814-
It's generally good to use `config.New` function to get the default configuration. It takes `local`, `lan` and `wan` parameters.
815-
Please see the [documentation](https://godoc.org/github.com/buraksezer/olric/config#New) to get more information.
816-
817-
Here is a sample configuration for a cluster with two hosts:
817+
Olric provides a function to generate default configuration to use in embedded-member mode:
818818

819819
```go
820-
package main
821-
822-
import (
823-
"context"
824-
"fmt"
825-
"log"
826-
"net"
827-
"reflect"
828-
"strconv"
829-
"time"
830-
831-
"github.com/buraksezer/olric"
832-
"github.com/buraksezer/olric/config"
833-
)
834-
835-
const (
836-
bindAddr string = "0.0.0.0"
837-
peerPortOne int = 5555
838-
peerPortTwo int = 6666
839-
)
840-
841-
func config1() *config.Config {
842-
c := config.New("local")
843-
// overwrite default values
844-
c.BindPort = 3320
845-
c.Name = net.JoinHostPort(bindAddr, strconv.Itoa(c.BindPort))
846-
847-
// Add the peer
848-
c.MemberlistConfig.BindPort = peerPortOne
849-
peerTwo := net.JoinHostPort(bindAddr, strconv.Itoa(peerPortTwo))
850-
c.Peers = []string{peerTwo}
851-
return c
852-
}
853-
854-
func config2() *config.Config {
855-
c := config.New("local")
856-
857-
// overwrite default values
858-
c.BindPort = 3322
859-
c.Name = net.JoinHostPort(bindAddr, strconv.Itoa(c.BindPort))
860-
861-
// Add the peer
862-
c.MemberlistConfig.BindPort = peerPortTwo
863-
peerOne := net.JoinHostPort(bindAddr, strconv.Itoa(peerPortOne))
864-
c.Peers = []string{peerOne}
865-
return c
866-
}
867-
868-
func main() {
869-
c1 := config1()
870-
db1, err := olric.New(c1)
871-
if err != nil {
872-
log.Fatalf("Failed to create Olric object: %v", err)
873-
}
874-
go func() {
875-
// Call Start at background. It's a blocker call.
876-
err = db1.Start()
877-
if err != nil {
878-
log.Fatalf("Failed to call Start: %v", err)
879-
}
880-
}()
881-
882-
c2 := config2()
883-
// This creates a single-node Olric cluster. It's good enough for experimenting.
884-
db2, err := olric.New(c2)
885-
if err != nil {
886-
log.Fatalf("Failed to create Olric object: %v", err)
887-
}
820+
import "github.com/buraksezer/olric/config"
821+
...
822+
c := config.New("local")
823+
```
888824

889-
go func() {
890-
// Call Start at background. It's a blocker call.
891-
err = db2.Start()
892-
if err != nil {
893-
log.Fatalf("Failed to call Start: %v", err)
894-
}
895-
}()
825+
The `New` function takes a parameter called `env`. It denotes the network environment and consumed by [hashicorp/memberlist](https://github.com/hashicorp/memberlist).
826+
Default configuration is good enough for distributed caching scenario. In order to see all configuration parameters, please take a look at [this](https://godoc.org/github.com/buraksezer/olric/config).
896827

897-
// You can use `config.Started` callback function to get notified about a server start
898-
// for the sake of simplicity, we just call time.After for some time.
899-
fmt.Println("Awaiting for background goroutines")
900-
<-time.After(time.Second)
828+
See [Sample Code](#sample-code) section for an introduction.
901829

902-
// Put 10 items into the DMap object.
903-
dm, err := db1.NewDMap("bucket-of-arbitrary-items")
904-
if err != nil {
905-
log.Fatalf("Failed to call NewDMap: %v", err)
906-
}
830+
### Client-Server Mode
907831

908-
fmt.Println("##")
909-
fmt.Println("Operations on a DMap instance:")
910-
err = dm.Put("string-key", "buraksezer")
911-
if err != nil {
912-
log.Fatalf("Failed to call Put: %v", err)
913-
}
914-
stringValue, err := dm.Get("string-key")
915-
if err != nil {
916-
log.Fatalf("Failed to call Get: %v", err)
917-
}
918-
fmt.Printf("Value for string-key: %v, reflect.TypeOf: %s\n", stringValue, reflect.TypeOf(stringValue))
832+
Olric provides **olricd** to implement client-server mode. olricd gets a YAML file for the configuration. The most basic functionality of olricd is that
833+
translating YAML configuration into Olric's configuration struct. A sample `olricd.yaml` file is being provided [here](https://github.com/buraksezer/olric/blob/master/cmd/olricd/olricd.yaml).
919834

920-
err = dm.Put("uint64-key", uint64(1988))
921-
if err != nil {
922-
log.Fatalf("Failed to call Put: %v", err)
923-
}
924-
uint64Value, err := dm.Get("uint64-key")
925-
if err != nil {
926-
log.Fatalf("Failed to call Get: %v", err)
927-
}
928-
fmt.Printf("Value for uint64-key: %v, reflect.TypeOf: %s\n", uint64Value, reflect.TypeOf(uint64Value))
835+
### Network Configuration
929836

930-
err = dm.Put("nil-key", nil)
931-
if err != nil {
932-
log.Fatalf("Failed to call Put: %v", err)
933-
}
934-
nilValue, err := dm.Get("nil-key")
935-
if err != nil {
936-
log.Fatalf("Failed to call Get: %v", err)
937-
}
938-
fmt.Printf("Value for nil-key: %v\n", nilValue)
939-
fmt.Println("##")
837+
In an Olric instance, there are two different TCP servers. One for Olric, and the other one is for memberlist. `BindAddr` is very
838+
critical to deploy a healthy Olric node. There are different scenarios:
940839

941-
// Don't forget the call Shutdown when you want to leave the cluster.
942-
ctx1, _ := context.WithTimeout(context.Background(), 10*time.Second)
943-
err = db1.Shutdown(ctx1)
944-
if err != nil {
945-
log.Printf("Failed to shutdown Olric: %v", err)
946-
}
840+
* You can freely set a domain name or IP address as `BindAddr` for both Olric and memberlist. Olric will resolve and use it to bind.
841+
* You can freely set `localhost`, `127.0.0.1` or `::1` as `BindAddr` in development environment for both Olric and memberlist.
842+
* You can freely set `0.0.0.0` as `BindAddr` for both Olric and memberlist. Olric will pick an IP address, if there is any.
843+
* If you don't set `BindAddr`, hostname will be used, and it will be resolved to get a valid IP address.
844+
* You can set a network interface by using `Config.Interface` and `Config.MemberlistInterface` fields. Olric will find an appropriate IP address for the given interfaces, if there is any.
845+
* You can set both `BindAddr` and interface parameters. In this case Olric will ensure that `BindAddr` is available on the given interface.
947846

948-
// Don't forget the call Shutdown when you want to leave the cluster.
949-
ctx2, _ := context.WithTimeout(context.Background(), 10*time.Second)
950-
err = db2.Shutdown(ctx2)
951-
if err != nil {
952-
log.Printf("Failed to shutdown Olric: %v", err)
953-
}
954-
}
955-
```
847+
You should know that Olric needs a single and stable IP address to function properly. If you don't know the IP address of the host at the deployment time,
848+
you can set `BindAddr` as `0.0.0.0`. Olric will very likely to find an IP address for you.
956849

957850
### Service Discovery
958851

@@ -1218,7 +1111,6 @@ func main() {
12181111

12191112
<-ctx.Done()
12201113

1221-
// Put 10 items into the DMap object.
12221114
dm, err := db.NewDMap("bucket-of-arbitrary-items")
12231115
if err != nil {
12241116
log.Fatalf("olric.NewDMap returned an error: %v", err)

cmd/olricd/olricd.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ olricd:
44
serializer: "msgpack"
55
keepAlivePeriod: "300s"
66
requestTimeout: "5s"
7-
partitionCount: 71
7+
partitionCount: 13
88
replicaCount: 1
99
writeQuorum: 1
1010
readQuorum: 1

cmd/olricd/server/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type olricd struct {
3333
Name string `yaml:"name"`
3434
BindAddr string `yaml:"bindAddr"`
3535
BindPort int `yaml:"bindPort"`
36+
Interface string `yaml:"interface"`
3637
ReplicationMode int `yaml:"replicationMode"`
3738
PartitionCount uint64 `yaml:"partitionCount"`
3839
LoadFactor float64 `yaml:"loadFactor"`
@@ -58,6 +59,7 @@ type memberlist struct {
5859
Environment string `yaml:"environment"` // required
5960
BindAddr string `yaml:"bindAddr"` // required
6061
BindPort int `yaml:"bindPort"` // required
62+
Interface string `yaml:"interface"`
6163
EnableCompression *bool `yaml:"enableCompression"`
6264
JoinRetryInterval string `yaml:"joinRetryInterval"` // required
6365
MaxJoinAttempts int `yaml:"maxJoinAttempts"` // required

cmd/olricd/server/memberlist.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"time"
2020

2121
"github.com/buraksezer/olric/config"
22-
"github.com/buraksezer/olric/internal/network"
2322
m "github.com/hashicorp/memberlist"
2423
)
2524

@@ -98,13 +97,8 @@ func newMemberlistConf(c *Config) (*m.Config, error) {
9897

9998
if c.Memberlist.AdvertiseAddr != nil {
10099
mc.AdvertiseAddr = *c.Memberlist.AdvertiseAddr
101-
} else {
102-
advertiseAddr, err := network.ParseOrLookupIP(mc.BindAddr)
103-
if err != nil {
104-
return nil, err
105-
}
106-
mc.AdvertiseAddr = advertiseAddr.String()
107100
}
101+
108102
if c.Memberlist.AdvertisePort != nil {
109103
mc.AdvertisePort = *c.Memberlist.AdvertisePort
110104
} else {

cmd/olricd/server/server.go

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -153,32 +153,34 @@ func New(c *Config) (*Olricd, error) {
153153

154154
s.log = log.New(logOutput, "", log.LstdFlags)
155155
s.config = &config.Config{
156-
Name: c.Olricd.Name, // deprecated, it will be removed in v0.3.0
157-
BindAddr: c.Olricd.BindAddr,
158-
BindPort: c.Olricd.BindPort,
159-
ServiceDiscovery: c.ServiceDiscovery,
160-
MemberlistConfig: mc,
161-
LogLevel: c.Logging.Level,
162-
JoinRetryInterval: joinRetryInterval,
163-
MaxJoinAttempts: c.Memberlist.MaxJoinAttempts,
164-
Peers: c.Memberlist.Peers,
165-
PartitionCount: c.Olricd.PartitionCount,
166-
ReplicaCount: c.Olricd.ReplicaCount,
167-
WriteQuorum: c.Olricd.WriteQuorum,
168-
ReadQuorum: c.Olricd.ReadQuorum,
169-
ReplicationMode: c.Olricd.ReplicationMode,
170-
ReadRepair: c.Olricd.ReadRepair,
171-
LoadFactor: c.Olricd.LoadFactor,
172-
MemberCountQuorum: c.Olricd.MemberCountQuorum,
173-
Logger: s.log,
174-
LogOutput: logOutput,
175-
LogVerbosity: c.Logging.Verbosity,
176-
Hasher: hasher.NewDefaultHasher(),
177-
Serializer: sr,
178-
KeepAlivePeriod: keepAlivePeriod,
179-
RequestTimeout: requestTimeout,
180-
Cache: cacheConfig,
181-
TableSize: c.Olricd.TableSize,
156+
Name: c.Olricd.Name, // deprecated, it will be removed in v0.3.0
157+
BindAddr: c.Olricd.BindAddr,
158+
BindPort: c.Olricd.BindPort,
159+
Interface: c.Olricd.Interface,
160+
ServiceDiscovery: c.ServiceDiscovery,
161+
MemberlistInterface: c.Memberlist.Interface,
162+
MemberlistConfig: mc,
163+
LogLevel: c.Logging.Level,
164+
JoinRetryInterval: joinRetryInterval,
165+
MaxJoinAttempts: c.Memberlist.MaxJoinAttempts,
166+
Peers: c.Memberlist.Peers,
167+
PartitionCount: c.Olricd.PartitionCount,
168+
ReplicaCount: c.Olricd.ReplicaCount,
169+
WriteQuorum: c.Olricd.WriteQuorum,
170+
ReadQuorum: c.Olricd.ReadQuorum,
171+
ReplicationMode: c.Olricd.ReplicationMode,
172+
ReadRepair: c.Olricd.ReadRepair,
173+
LoadFactor: c.Olricd.LoadFactor,
174+
MemberCountQuorum: c.Olricd.MemberCountQuorum,
175+
Logger: s.log,
176+
LogOutput: logOutput,
177+
LogVerbosity: c.Logging.Verbosity,
178+
Hasher: hasher.NewDefaultHasher(),
179+
Serializer: sr,
180+
KeepAlivePeriod: keepAlivePeriod,
181+
RequestTimeout: requestTimeout,
182+
Cache: cacheConfig,
183+
TableSize: c.Olricd.TableSize,
182184
}
183185
return s, nil
184186
}

config/config.go

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ const (
4141
)
4242

4343
const (
44+
// DefaultPort is for Olric
4445
DefaultPort = 3320
4546

47+
// DefaultDiscoveryPort is for memberlist
4648
DefaultDiscoveryPort = 3322
4749

4850
// DefaultPartitionCount denotes default partition count in the cluster.
@@ -178,22 +180,20 @@ type CacheConfig struct {
178180

179181
// Config is the configuration to create a Olric instance.
180182
type Config struct {
183+
// Interface denotes a binding interface. It can be used instead of BindAddr if the interface is known but not the address.
184+
// If both are provided, then Olric verifies that the interface has the bind address that is provided.
185+
Interface string
186+
181187
// LogVerbosity denotes the level of message verbosity. The default value is 3. Valid values are between 1 to 6.
182188
LogVerbosity int32
183189

184190
// Default LogLevel is DEBUG. Valid ones: "DEBUG", "WARN", "ERROR", "INFO"
185191
LogLevel string
186192

187-
// Name of this node in the cluster. This must be unique in the cluster. If this is not set,
188-
// Olric will set it to the hostname of the running machine. Example: node1.my-cluster.net
189-
//
190-
// Name is also used by the TCP server as Addr. It should be an IP address or domain name of the server.
191-
Name string
192-
193-
// Addr to bind
193+
// BindAddr denotes the address that Olric will bind to for communication with other Olric nodes.
194194
BindAddr string
195195

196-
// Port to bind
196+
// BindPort denotes the address that Olric will bind to for communication with other Olric nodes.
197197
BindPort int
198198

199199
// KeepAlivePeriod denotes whether the operating system should send keep-alive messages on the connection.
@@ -267,6 +267,11 @@ type Config struct {
267267

268268
ServiceDiscovery map[string]interface{}
269269

270+
// Interface denotes a binding interface. It can be used instead of memberlist.Config.BindAddr if the interface is
271+
// known but not the address. If both are provided, then Olric verifies that the interface has the bind address that
272+
// is provided.
273+
MemberlistInterface string
274+
270275
// MemberlistConfig is the memberlist configuration that Olric will
271276
// use to do the underlying membership management and gossip. Some
272277
// fields in the MemberlistConfig will be overwritten by Olric no
@@ -413,23 +418,6 @@ func (c *Config) Sanitize() error {
413418
c.BindPort = DefaultPort
414419
}
415420

416-
// TODO: Config.Name is deprecated and it will be removed in v0.3.0
417-
if c.Name == "" {
418-
c.Name = c.BindAddr + ":" + strconv.Itoa(c.BindPort)
419-
} else {
420-
c.Logger.Printf("[WARN] Config.Name is deprecated. Please use BindAddr and BindPort instead of Config.name")
421-
host, _port, err := net.SplitHostPort(c.Name)
422-
if err != nil {
423-
return err
424-
}
425-
port, err := strconv.Atoi(_port)
426-
if err != nil {
427-
return err
428-
}
429-
c.BindAddr = host
430-
c.BindPort = port
431-
}
432-
433421
if c.LoadFactor == 0 {
434422
c.LoadFactor = DefaultLoadFactor
435423
}

0 commit comments

Comments
 (0)