When trying to create a ConnectionMultiplexer instance, it throws a PlatformNotSupportedException.
When trying to create the same connection, but using the ip address instead of the hostname, it works just fine.
Include "StackExchange.Redis": "1.1.604-alpha" in project.json
// works fine
var redis1 = StackExchange.Redis.ConnectionMultiplexer.Connect("127.0.0.1");
// thows
var redis2 = StackExchange.Redis.ConnectionMultiplexer.Connect("localhost");
at System.Threading.Tasks.TaskFactory`1.FromAsyncImpl[TArg1,TArg2](Func`5 beginMethod, Func`2 endFunction, Action`1 endAction, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions)
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, String host, Int32 port)
at StackExchange.Redis.SocketManager.BeginConnect(EndPoint endpoint, ISocketCallback callback, ConnectionMultiplexer multiplexer, TextWriter log)
at StackExchange.Redis.PhysicalConnection.BeginConnect(TextWriter log)
at StackExchange.Redis.PhysicalBridge.GetConnection(TextWriter log)
at StackExchange.Redis.ServerEndPoint..ctor(ConnectionMultiplexer multiplexer, EndPoint endpoint, TextWriter log)
at StackExchange.Redis.ConnectionMultiplexer.<ReconfigureAsync>d__119.MoveNext()
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at StackExchange.Redis.ConnectionMultiplexer.ConnectImpl(Func`1 multiplexerFactory, TextWriter log)
at ConsoleApplication.Program.Main(String[] args)
---> (Inner Exception #0) System.PlatformNotSupportedException: Sockets on this platform are invalid for use after a failed connection attempt, and as a result do not support attempts to connect to multiple endpoints.
at System.Net.Sockets.Socket.BeginConnect(String host, Int32 port, AsyncCallback requestCallback, Object state)
at System.Threading.Tasks.TaskFactory`1.FromAsyncImpl[TArg1,TArg2](Func`5 beginMethod, Func`2 endFunction, Action`1 endAction, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions)
at System.Net.Sockets.SocketTaskExtensions.ConnectAsync(Socket socket, String host, Int32 port)
at StackExchange.Redis.SocketManager.BeginConnect(EndPoint endpoint, ISocketCallback callback, ConnectionMultiplexer multiplexer, TextWriter log)
at StackExchange.Redis.PhysicalConnection.BeginConnect(TextWriter log)
at StackExchange.Redis.PhysicalBridge.GetConnection(TextWriter log)
at StackExchange.Redis.ServerEndPoint..ctor(ConnectionMultiplexer multiplexer, EndPoint endpoint, TextWriter log)
at StackExchange.Redis.ConnectionMultiplexer.<ReconfigureAsync>d__119.MoveNext()<---
OS: OS X 10.11.5
$ dotnet --info
.NET Command Line Tools (1.0.0-preview1-002702)
Product Information:
Version: 1.0.0-preview1-002702
Commit Sha: 6cde21225e
Runtime Environment:
OS Name: Mac OS X
OS Version: 10.11
OS Platform: Darwin
RID: osx.10.11-x64
Hmm, at first glance this seems to be in the core socket code not taking hostnames on OS X. I'll take a peek, but it appears that this is what you're hitting: https://github.com/dotnet/corefx/issues/5829#issuecomment-207553272
This one will be rough, if we're not allowed to connect to hostname on those platforms...man that's crap. It's also a terrible way to find out it doesn't work. I'm pinging the MS guys on this one, I don't agree with the "fix" currently in place here.
Yeah. Weird way to say it was "fixed"...
As a workaround, I'm checking if what i'm getting as a server address isn't an actual IP and resolving the hostname ip address before creating the redis connection.
Hope it gets really fixed in CoreFx!
Just as a comment if someone is using coreclr from docker (linux flavor of coreclr): the same issue it's happening there. Also, the same workaround can be applied.
@PabloZaiden FYI: I've added an issue to CoreFX if you want to follow along: https://github.com/dotnet/corefx/issues/8768 We'll get this fixed one way or another soon, but let's see what initial MS reaction is and which route we should take for a temp & long-term solution on .NET Core.
This manifested in a slightly different way for me. Sharing details for others who might try searching for this error text. Full gist here, showing a connection to redis from redis-cli. The error in the StringBuilder after connection failure is:
Connecting redis.dotkube:6379/Interactive...
BeginConnect: redis.dotkube:6379
Connect redis.dotkube:6379/Interactive failed: Sockets on this platform are invalid for use after a failed connection attempt, and as a result do not support attempts to connect to multiple endpoints.
I resolved this by changing my CMD from ./publish/<exec> to set -x; apt -qqy update; apt -qqy install dnsutils; export DOTKUBE_REDIS_SERVER=$(dig +short +search redis.dotkube); ./publish/Dotkube.Api.
(Edit: this was while being deployed to a Kubernetes cluster using Docker.)
Nick, any thoughts to patching this temporarily? The underlying issue in core library is tagged as 1.2 which is about 8 months away.
anyone have a work around here besides finding the ip address of the redis instance?
@KyleGobel as a workaround, try the code below, worked for me on Ubuntu 16.04 x64:
As a connection string I used the one from Azure Portal, but had to use non-SSL connection, replace port 6380 with 6379 and ssl=False.
With SSL had the following error:
System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
ConfigurationOptions config = ConfigurationOptions.Parse(connectionString);
DnsEndPoint addressEndpoint = config.EndPoints.First() as DnsEndPoint;
int port = addressEndpoint.Port;
bool isIp = IsIpAddress(addressEndpoint.Host);
if (!isIp)
{
//Please Don't use this line in blocking context. Please remove ".Result"
//Just for test purposes
IPHostEntry ip = Dns.GetHostEntryAsync(addressEndpoint.Host).Result;
config.EndPoints.Remove(addressEndpoint);
config.EndPoints.Add(ip.AddressList.First(), port);
}
var redis = ConnectionMultiplexer.Connect(config);
IsIpAddress method code:
bool IsIpAddress(string host)
{
string ipPattern = @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b";
return Regex.IsMatch(host, ipPattern);
}
Just encountered this issue as well using version StackExchange.Redis": "1.1.608".
We need to address this in 2.0 if not before (I need to re-sync on where netstandard is headed with the behavior here). Tracking for 2.0 in #528
Hi guys,
any ETA when this fix will be on Nuget?
I'd love to have these extension methods based on the workaround given by @trollsic:
```C#
using Microsoft.Extensions.Caching.Redis;
using StackExchange.Redis;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
namespace Microsoft.Extensions.DependencyInjection
{
public static class RedisCacheOptionsExtensions
{
public static void ResolveDns(this RedisCacheOptions options)
{
// Assume that the first part is host and port.
var hostWithPort = options.Configuration.Substring(0, options.Configuration.IndexOf(","));
var resolved = TryResolveDns(hostWithPort);
var replaced = options.Configuration.Replace(hostWithPort, resolved);
options.Configuration = replaced;
}
private static string TryResolveDns(string redisUrl)
{
var config = ConfigurationOptions.Parse(redisUrl);
foreach (DnsEndPoint addressEndpoint in config.EndPoints)
{
var port = addressEndpoint.Port;
var isIp = IsIpAddress(addressEndpoint.Host);
if (!isIp)
{
var ip = Dns.GetHostEntryAsync(addressEndpoint.Host).GetAwaiter().GetResult();
return $"{ip.AddressList.First(x => IsIpAddress(x.ToString()))}:{port}";
}
}
return redisUrl;
}
private static bool IsIpAddress(string host)
{
return Regex.IsMatch(host, @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b");
}
}
}
Usage:
```C#
public IConfigurationRoot Configuration { get; private set; }
...
services.AddDistributedRedisCache(options =>
{
this.Configuration.GetSection("ConnectionStrings:RedisConnection").Bind(options);
options.ResolveDns();
});
Known issues:
@LonghronShen A good sample and I use it in my project now~
@LonghronShen, Thanks for your sample!
Getting null value for
var conn = serviceScope.ServiceProvider.GetService
Any idea whats wrong?
for ConnectionMultiplexer
From following the above links it looks like the underlying issue has been resolved in dot net core 2.0, and this error will no longer affect users that upgrade to dot net core 2.0. Is that correct?
@tobyhei is correct, this was an issue beneath the library that's now supported in .NET Core 2.0 onward. I'm going to close this out as the root cause wasn't the lib and has been resolved for a while now :)
Most helpful comment
I'd love to have these extension methods based on the workaround given by @trollsic:
```C#
using Microsoft.Extensions.Caching.Redis;
using StackExchange.Redis;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
namespace Microsoft.Extensions.DependencyInjection
{
}
Known issues: