From 5a74c1695d44ae89259d63217ff53b23142bc910 Mon Sep 17 00:00:00 2001 From: "Brint E. Kriebel" Date: Sat, 28 May 2022 10:26:58 -0700 Subject: [PATCH] Add support for Redis Sentinel (#707) --- config-sample.yaml | 8 +++++++ go.mod | 4 ++-- go.sum | 7 ++++-- pkg/config/config.go | 20 ++++++++++++----- pkg/service/wire.go | 46 ++++++++++++++++++++++++------------- pkg/service/wire_gen.go | 50 ++++++++++++++++++++++++++--------------- 6 files changed, 91 insertions(+), 44 deletions(-) diff --git a/config-sample.yaml b/config-sample.yaml index 1e67f6d93..e845ddb97 100644 --- a/config-sample.yaml +++ b/config-sample.yaml @@ -9,6 +9,14 @@ redis: # db: 0 # username: myuser # password: mypassword + # To use sentinel remove the address key above and add the following + # sentinel_master_name: livekit + # sentinel_addresses: + # - livekit-redis-node-0.livekit-redis-headless:26379 + # - livekit-redis-node-1.livekit-redis-headless:26379 + # If you use a different set of credentials for sentinel add + # sentinel_username: user + # sentinel_password: pass # WebRTC configuration rtc: diff --git a/go.mod b/go.mod index 220abd88a..01a3fd59f 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/gammazero/deque v0.1.0 github.com/gammazero/workerpool v1.1.2 github.com/go-logr/logr v1.2.2 - github.com/go-redis/redis/v8 v8.11.3 + github.com/go-redis/redis/v8 v8.11.4 github.com/google/wire v0.5.0 github.com/gorilla/websocket v1.4.2 github.com/hashicorp/golang-lru v0.5.4 @@ -48,7 +48,7 @@ require ( require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/d5/tengo/v2 v2.10.1 github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/go.sum b/go.sum index 979e8c264..ee74e14f4 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,9 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bep/debounce v1.2.0 h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo= github.com/bep/debounce v1.2.0/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -67,8 +68,9 @@ github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= -github.com/go-redis/redis/v8 v8.11.3 h1:GCjoYp8c+yQTJfc0n69iwSiHjvuAdruxl7elnZCxgt8= github.com/go-redis/redis/v8 v8.11.3/go.mod h1:xNJ9xDG09FsIPwh3bWdk+0oDWHbtF9rPN0F/oD9XeKc= +github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg= +github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -169,6 +171,7 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= +github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/pion/datachannel v1.5.2 h1:piB93s8LGmbECrpO84DnkIVWasRMk3IimbcXkTQLE6E= diff --git a/pkg/config/config.go b/pkg/config/config.go index 551328aa6..57f0a232f 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -119,11 +119,15 @@ type VideoConfig struct { } type RedisConfig struct { - Address string `yaml:"address"` - Username string `yaml:"username"` - Password string `yaml:"password"` - DB int `yaml:"db"` - UseTLS bool `yaml:"use_tls"` + Address string `yaml:"address"` + Username string `yaml:"username"` + Password string `yaml:"password"` + DB int `yaml:"db"` + UseTLS bool `yaml:"use_tls"` + MasterName string `yaml:"sentinel_master_name"` + SentinelUsername string `yaml:"sentinel_username"` + SentinelPassword string `yaml:"sentinel_password"` + SentinelAddresses []string `yaml:"sentinel_addresses"` } type RoomConfig struct { @@ -289,7 +293,11 @@ func NewConfig(confString string, c *cli.Context) (*Config, error) { } func (conf *Config) HasRedis() bool { - return conf.Redis.Address != "" + return conf.Redis.Address != "" || conf.Redis.SentinelAddresses != nil +} + +func (conf *Config) UseSentinel() bool { + return conf.Redis.SentinelAddresses != nil } func (conf *Config) updateFromCLI(c *cli.Context) error { diff --git a/pkg/service/wire.go b/pkg/service/wire.go index af8e1a223..8d0b7eeee 100644 --- a/pkg/service/wire.go +++ b/pkg/service/wire.go @@ -109,25 +109,39 @@ func createRedisClient(conf *config.Config) (*redis.Client, error) { return nil, nil } - logger.Infow("using multi-node routing via redis", "addr", conf.Redis.Address) - rcOptions := &redis.Options{ - Addr: conf.Redis.Address, - Username: conf.Redis.Username, - Password: conf.Redis.Password, - DB: conf.Redis.DB, - } + var rc *redis.Client + var tlsConfig *tls.Config + if conf.Redis.UseTLS { - rcOptions = &redis.Options{ - Addr: conf.Redis.Address, - Username: conf.Redis.Username, - Password: conf.Redis.Password, - DB: conf.Redis.DB, - TLSConfig: &tls.Config{ - MinVersion: tls.VersionTLS12, - }, + tlsConfig = &tls.Config{ + MinVersion: tls.VersionTLS12, } } - rc := redis.NewClient(rcOptions) + + if conf.UseSentinel() { + logger.Infow("using multi-node routing via redis", "sentinel", true, "addr", conf.Redis.SentinelAddresses, "masterName", conf.Redis.MasterName) + rcOptions := &redis.FailoverOptions{ + SentinelAddrs: conf.Redis.SentinelAddresses, + SentinelUsername: conf.Redis.SentinelUsername, + SentinelPassword: conf.Redis.SentinelPassword, + MasterName: conf.Redis.MasterName, + Username: conf.Redis.Username, + Password: conf.Redis.Password, + DB: conf.Redis.DB, + TLSConfig: tlsConfig, + } + rc = redis.NewFailoverClient(rcOptions) + } else { + logger.Infow("using multi-node routing via redis", "sentinel", false, "addr", conf.Redis.Address) + rcOptions := &redis.Options{ + Addr: conf.Redis.Address, + Username: conf.Redis.Username, + Password: conf.Redis.Password, + DB: conf.Redis.DB, + TLSConfig: tlsConfig, + } + rc = redis.NewClient(rcOptions) + } if err := rc.Ping(context.Background()).Err(); err != nil { err = errors.Wrap(err, "unable to connect to redis") diff --git a/pkg/service/wire_gen.go b/pkg/service/wire_gen.go index 45541d374..850ccb826 100644 --- a/pkg/service/wire_gen.go +++ b/pkg/service/wire_gen.go @@ -1,8 +1,7 @@ // Code generated by Wire. DO NOT EDIT. //go:generate go run github.com/google/wire/cmd/wire -//go:build !wireinject -// +build !wireinject +//+build !wireinject package service @@ -133,25 +132,40 @@ func createRedisClient(conf *config.Config) (*redis.Client, error) { if !conf.HasRedis() { return nil, nil } - logger.Infow("using multi-node routing via redis", "addr", conf.Redis.Address) - rcOptions := &redis.Options{ - Addr: conf.Redis.Address, - Username: conf.Redis.Username, - Password: conf.Redis.Password, - DB: conf.Redis.DB, - } + + var rc *redis.Client + var tlsConfig *tls.Config + if conf.Redis.UseTLS { - rcOptions = &redis.Options{ - Addr: conf.Redis.Address, - Username: conf.Redis.Username, - Password: conf.Redis.Password, - DB: conf.Redis.DB, - TLSConfig: &tls.Config{ - MinVersion: tls.VersionTLS12, - }, + tlsConfig = &tls.Config{ + MinVersion: tls.VersionTLS12, } } - rc := redis.NewClient(rcOptions) + + if conf.UseSentinel() { + logger.Infow("using multi-node routing via redis", "sentinel", true, "addr", conf.Redis.SentinelAddresses, "masterName", conf.Redis.MasterName) + rcOptions := &redis.FailoverOptions{ + SentinelAddrs: conf.Redis.SentinelAddresses, + SentinelUsername: conf.Redis.SentinelUsername, + SentinelPassword: conf.Redis.SentinelPassword, + MasterName: conf.Redis.MasterName, + Username: conf.Redis.Username, + Password: conf.Redis.Password, + DB: conf.Redis.DB, + TLSConfig: tlsConfig, + } + rc = redis.NewFailoverClient(rcOptions) + } else { + logger.Infow("using multi-node routing via redis", "sentinel", false, "addr", conf.Redis.Address) + rcOptions := &redis.Options{ + Addr: conf.Redis.Address, + Username: conf.Redis.Username, + Password: conf.Redis.Password, + DB: conf.Redis.DB, + TLSConfig: tlsConfig, + } + rc = redis.NewClient(rcOptions) + } if err := rc.Ping(context.Background()).Err(); err != nil { err = errors.Wrap(err, "unable to connect to redis")