首页 新闻 会员 周边 捐助

.NET Core在Linux上无法通过主机名连接redis

0
悬赏园豆:30 [已解决问题] 解决于 2016-12-31 13:50

使用 Microsoft.Extensions.Caching.Redis.Core 连接 redis,在 Linux 上运行时报下面的错误:

This platform does not support connecting sockets to DNS endpoints via the instance Connect and ConnectAsync methods, due to the potential for a host name to map to multiple IP addresses and sockets becoming invalid for use after a failed connect attempt. Use the static ConnectAsync method, or provide to the instance methods the specific IPAddress desired.
   at System.Net.Sockets.Socket.ThrowIfNotSupportsMultipleConnectAttempts()
   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()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at StackExchange.Redis.ConnectionMultiplexer.<ConnectAsync>d__72.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Extensions.Caching.Redis.RedisCache.<ConnectAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Extensions.Caching.Redis.RedisCache.<GetAndRefreshAsync>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Extensions.Caching.Redis.RedisCache.<RefreshAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Session.DistributedSession.<CommitAsync>d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Session.SessionMiddleware.<Invoke>d__9.MoveNext()

而换成IP地址就能正常连接。

问题补充:

问题发生在 StackExchange.Redis 的源码中下面的部分:

socket.ConnectAsync(dnsEndpoint.Host, dnsEndpoint.Port).ContinueWith(t =>
{
    multiplexer.LogLocked(log, "EndConnect: {0}", formattedEndpoint);
    EndConnectImpl(t, multiplexer, log, tuple);
    multiplexer.LogLocked(log, "Connect complete: {0}", formattedEndpoint);
});
dudu的主页 dudu | 高人七级 | 园豆:30948
提问于:2016-12-30 22:02
< >
分享
最佳答案
0

在github上提交了一个解决这个问题的pull request:Wordaround for connecting redis via host name on Linux

dudu | 高人七级 |园豆:30948 | 2016-12-31 13:50

异常是在 System.Net.Sockets.Socket.BeginConnect() 的下面这行代码抛出的:

ThrowIfNotSupportsMultipleConnectAttempts();

它的对应实现是:

private static void ThrowIfNotSupportsMultipleConnectAttempts()
{
    if (!SocketPal.SupportsMultipleConnectAttempts)
    {
        throw new PlatformNotSupportedException(SR.net_sockets_connect_multiaddress_notsupported);
    }
}

在 SocketPal.Windows.cs 中 SupportsMultipleConnectAttempts 的值是 true 。

在 SocketPal.Unit.cs 中 SupportsMultipleConnectAttempts 的值是 false 。

dudu | 园豆:30948 (高人七级) | 2016-12-31 14:18
其他回答(3)
0

异常不也这么说的吗,就是说了不支持的

收获园豆:15
花飘水流兮 | 园豆:13615 (专家六级) | 2016-12-30 22:17
0

这个本身就不支持,没什么好说的。。。

收获园豆:15
XiaoFaye | 园豆:3087 (老鸟四级) | 2016-12-31 13:46
0

这个问题我很久之前就提到过了,见:https://github.com/StackExchange/StackExchange.Redis/issues/454

同一个host可能绑定多个 ip ,所以他们把这个锅退给了CoreCLR。


Savorboard | 园豆:611 (小虾三级) | 2016-12-31 14:20
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册