Skip to content

Commit 3d8c72b

Browse files
committed
support for envoyproxy
1 parent 84566e7 commit 3d8c72b

10 files changed

Lines changed: 85 additions & 10 deletions

docs/Configuration.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ The `ConfigurationOptions` object has a wide range of properties, all of which a
8686
| name={string} | `ClientName` | `null` | Identification for the connection within redis |
8787
| password={string} | `Password` | `null` | Password for the redis server |
8888
| user={string} | `User` | `null` | User for the redis server (for use with ACLs on redis 6 and above) |
89-
| proxy={proxy type} | `Proxy` | `Proxy.None` | Type of proxy in use (if any); for example "twemproxy" |
89+
| proxy={proxy type} | `Proxy` | `Proxy.None` | Type of proxy in use (if any); for example "twemproxy/envoyproxy" |
9090
| resolveDns={bool} | `ResolveDns` | `false` | Specifies that DNS resolution should be explicit and eager, rather than implicit |
9191
| serviceName={string} | `ServiceName` | `null` | Used for connecting to a sentinel master service |
9292
| ssl={bool} | `Ssl` | `false` | Specifies that SSL encryption should be used |
@@ -178,6 +178,18 @@ var options = new ConfigurationOptions
178178
};
179179
```
180180

181+
envoyproxy
182+
---
183+
184+
[EnvoyProxy](https://github.com/envoyproxy/envoy) is a tool that allows to front a redis cluster with a set of proxies, with inbuilt discovery and fault tolerance. The feature-set available to Envoyproxy is reduced. To avoid having to configure this manually, the `Proxy` option can be used:
185+
```csharp
186+
var options = new ConfigurationOptions+{
187+
EndPoints = { "my-proxy1", "my-proxy2", "my-proxy3" },
188+
Proxy = Proxy.EnvoyProxy
189+
};
190+
```
191+
192+
181193
Tiebreakers and Configuration Change Announcements
182194
---
183195

src/StackExchange.Redis/CommandMap.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,39 @@ public sealed class CommandMap
5151
RedisCommand.SAVE, RedisCommand.SHUTDOWN, RedisCommand.SLAVEOF, RedisCommand.SLOWLOG, RedisCommand.SYNC, RedisCommand.TIME
5252
});
5353

54+
/// <summary>
55+
/// The commands available to <a href="https://github.com/envoyproxy/envoy">envoyproxy</a> via
56+
/// </summary>
57+
public static CommandMap Envoyproxy { get; } = CreateImpl(null, exclusions: new HashSet<RedisCommand>
58+
{
59+
// not in <a href="https://github.com/envoyproxy/envoy/blob/0fae6970ddaf93f024908ba304bbd2b34e997a51/source/extensions/filters/network/common/redis/supported_commands.h">supported_commands.h</a>
60+
RedisCommand.KEYS, RedisCommand.MIGRATE, RedisCommand.MOVE, RedisCommand.OBJECT, RedisCommand.RANDOMKEY,
61+
RedisCommand.RENAME, RedisCommand.RENAMENX, RedisCommand.SORT, RedisCommand.SCAN,
62+
63+
RedisCommand.BITOP, RedisCommand.MSET, RedisCommand.MSETNX,
64+
65+
RedisCommand.BLPOP, RedisCommand.BRPOP, RedisCommand.BRPOPLPUSH, // yeah, me neither!
66+
67+
RedisCommand.PSUBSCRIBE, RedisCommand.PUBLISH, RedisCommand.PUNSUBSCRIBE, RedisCommand.SUBSCRIBE, RedisCommand.UNSUBSCRIBE,
68+
69+
RedisCommand.DISCARD, RedisCommand.EXEC, RedisCommand.MULTI, RedisCommand.UNWATCH, RedisCommand.WATCH,
70+
71+
RedisCommand.SCRIPT,
72+
73+
RedisCommand.ECHO, RedisCommand.PING, RedisCommand.QUIT, RedisCommand.SELECT,
74+
75+
RedisCommand.BGREWRITEAOF, RedisCommand.BGSAVE, RedisCommand.CLIENT, RedisCommand.CLUSTER, RedisCommand.CONFIG, RedisCommand.DBSIZE,
76+
RedisCommand.DEBUG, RedisCommand.FLUSHALL, RedisCommand.FLUSHDB, RedisCommand.INFO, RedisCommand.LASTSAVE, RedisCommand.MONITOR, RedisCommand.REPLICAOF,
77+
RedisCommand.SAVE, RedisCommand.SHUTDOWN, RedisCommand.SLAVEOF, RedisCommand.SLOWLOG, RedisCommand.SYNC, RedisCommand.TIME,
78+
79+
// supported by envoy but not enabled by stack exchange
80+
// RedisCommand.BITFIELD,
81+
//
82+
// RedisCommand.GEORADIUS_RO,
83+
// RedisCommand.GEORADIUSBYMEMBER_RO,
84+
});
85+
86+
5487
/// <summary>
5588
/// The commands available to <a href="https://ssdb.io/">SSDB</a>.
5689
/// </summary>

src/StackExchange.Redis/ConfigurationOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ public CommandMap CommandMap
275275
get => commandMap ?? Proxy switch
276276
{
277277
Proxy.Twemproxy => CommandMap.Twemproxy,
278+
Proxy.Envoyproxy => CommandMap.Envoyproxy,
278279
_ => CommandMap.Default,
279280
};
280281
set => commandMap = value ?? throw new ArgumentNullException(nameof(value));

src/StackExchange.Redis/ConnectionMultiplexer.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1807,6 +1807,7 @@ internal async Task<bool> ReconfigureAsync(bool first, bool reconfigureAll, LogP
18071807
switch (server.ServerType)
18081808
{
18091809
case ServerType.Twemproxy:
1810+
case ServerType.Envoyproxy:
18101811
case ServerType.Standalone:
18111812
standaloneCount++;
18121813
break;
@@ -1831,6 +1832,7 @@ internal async Task<bool> ReconfigureAsync(bool first, bool reconfigureAll, LogP
18311832
switch (server.ServerType)
18321833
{
18331834
case ServerType.Twemproxy:
1835+
case ServerType.Envoyproxy:
18341836
case ServerType.Sentinel:
18351837
case ServerType.Standalone:
18361838
case ServerType.Cluster:
@@ -1879,6 +1881,10 @@ internal async Task<bool> ReconfigureAsync(bool first, bool reconfigureAll, LogP
18791881
{
18801882
ServerSelectionStrategy.ServerType = ServerType.Twemproxy;
18811883
}
1884+
else if (RawConfig.Proxy == Proxy.Envoyproxy)
1885+
{
1886+
ServerSelectionStrategy.ServerType = ServerType.Envoyproxy;
1887+
}
18821888
else if (standaloneCount == 0 && sentinelCount > 0)
18831889
{
18841890
ServerSelectionStrategy.ServerType = ServerType.Sentinel;

src/StackExchange.Redis/Enums/Proxy.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ public enum Proxy
1313
/// Communication via <a href="https://github.com/twitter/twemproxy">twemproxy</a>.
1414
/// </summary>
1515
Twemproxy,
16+
/// <summary>
17+
/// Communication via <a href="https://github.com/envoyproxy/envoy">envoyproxy</a>
18+
/// </summary>
19+
Envoyproxy
1620
}
1721

1822
internal static class ProxyExtesions
@@ -23,6 +27,7 @@ internal static class ProxyExtesions
2327
public static bool SupportsDatabases(this Proxy proxy) => proxy switch
2428
{
2529
Proxy.Twemproxy => false,
30+
Proxy.Envoyproxy => false,
2631
_ => true
2732
};
2833

@@ -32,6 +37,7 @@ internal static class ProxyExtesions
3237
public static bool SupportsPubSub(this Proxy proxy) => proxy switch
3338
{
3439
Proxy.Twemproxy => false,
40+
Proxy.Envoyproxy => false,
3541
_ => true
3642
};
3743

@@ -41,6 +47,7 @@ internal static class ProxyExtesions
4147
public static bool SupportsServerApi(this Proxy proxy) => proxy switch
4248
{
4349
Proxy.Twemproxy => false,
50+
Proxy.Envoyproxy => false,
4451
_ => true
4552
};
4653
}

src/StackExchange.Redis/Enums/ServerType.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ public enum ServerType
2121
/// Distributed redis installation via <a href="https://github.com/twitter/twemproxy">twemproxy</a>.
2222
/// </summary>
2323
Twemproxy,
24+
/// <summary>
25+
/// Redis cluster via <a href="https://github.com/envoyproxy/envoy">envoyproxy</a>
26+
/// </summary>
27+
Envoyproxy
2428
}
2529

2630
internal static class ServerTypeExtesions
@@ -30,6 +34,7 @@ internal static class ServerTypeExtesions
3034
/// </summary>
3135
public static bool HasSinglePrimary(this ServerType type) => type switch
3236
{
37+
ServerType.Envoyproxy => true,
3338
_ => false
3439
};
3540

@@ -39,6 +44,7 @@ internal static class ServerTypeExtesions
3944
public static bool SupportsAutoConfigure(this ServerType type) => type switch
4045
{
4146
ServerType.Twemproxy => false,
47+
ServerType.Envoyproxy => false,
4248
_ => true
4349
};
4450
}

src/StackExchange.Redis/PhysicalConnection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ internal Message GetSelectDatabaseCommand(int targetDatabase, Message message)
573573
}
574574
int available = serverEndpoint.Databases;
575575

576-
if (!serverEndpoint.HasDatabases) // only db0 is available on cluster/twemproxy
576+
if (!serverEndpoint.HasDatabases) // only db0 is available on cluster/twemproxy/envoyproxy
577577
{
578578
if (targetDatabase != 0)
579579
{ // should never see this, since the API doesn't allow it; thus not too worried about ExceptionFactory

src/StackExchange.Redis/RedisBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ private ResultProcessor.TimingProcessor.TimerMessage GetTimerMessage(CommandFlag
108108
if (map.IsAvailable(RedisCommand.ECHO))
109109
return ResultProcessor.TimingProcessor.CreateMessage(-1, flags, RedisCommand.ECHO, RedisLiterals.PING);
110110
// as our fallback, we'll do something odd... we'll treat a key like a value, out of sheer desperation
111-
// note: this usually means: twemproxy - in which case we're fine anyway, since the proxy does the routing
111+
// note: this usually means: twemproxy/envoyproxy - in which case we're fine anyway, since the proxy does the routing
112112
return ResultProcessor.TimingProcessor.CreateMessage(0, flags, RedisCommand.EXISTS, (RedisValue)multiplexer.UniqueId);
113113
}
114114

src/StackExchange.Redis/ServerEndPoint.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,19 @@ public ServerEndPoint(ConnectionMultiplexer multiplexer, EndPoint endpoint)
5757
serverType = ServerType.Standalone;
5858
ConfigCheckSeconds = Multiplexer.RawConfig.ConfigCheckSeconds;
5959
// overrides for twemproxy
60-
if (multiplexer.RawConfig.Proxy == Proxy.Twemproxy)
60+
switch (multiplexer.RawConfig.Proxy)
6161
{
62-
databases = 1;
63-
serverType = ServerType.Twemproxy;
62+
case Proxy.Twemproxy:
63+
databases = 1;
64+
serverType = ServerType.Twemproxy;
65+
break;
66+
case Proxy.Envoyproxy:
67+
databases = 1;
68+
serverType = ServerType.Envoyproxy;
69+
break;
70+
case Proxy.None:
71+
break;
72+
6473
}
6574
}
6675

@@ -329,7 +338,7 @@ internal void AddScript(string script, byte[] hash)
329338

330339
internal async Task AutoConfigureAsync(PhysicalConnection connection, LogProxy log = null)
331340
{
332-
if (serverType == ServerType.Twemproxy)
341+
if (!serverType.SupportsAutoConfigure())
333342
{
334343
// don't try to detect configuration; all the config commands are disabled, and
335344
// the fallback master/replica detection won't help

src/StackExchange.Redis/ServerSelectionStrategy.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,10 @@ public ServerEndPoint Select(Message message, bool allowDisconnected = false)
110110
switch (ServerType)
111111
{
112112
case ServerType.Cluster:
113-
case ServerType.Twemproxy: // strictly speaking twemproxy uses a different hashing algorithm, but the hash-tag behavior is
114-
// the same, so this does a pretty good job of spotting illegal commands before sending them
115-
113+
// strictly speaking twemproxy/envoyproxy does not use a hashing algorithm, but the hash-tag behavior is
114+
// the same, so this does a pretty good job of spotting illegal commands before sending them
115+
case ServerType.Twemproxy:
116+
case ServerType.Envoyproxy:
116117
slot = message.GetHashSlot(this);
117118
if (slot == MultipleSlots) throw ExceptionFactory.MultiSlot(multiplexer.IncludeDetailInExceptions, message);
118119
break;

0 commit comments

Comments
 (0)