Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a timeout for socket connection #2791

Merged
merged 5 commits into from
Feb 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/Orleans/Configuration/MessagingConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ namespace Orleans.Runtime.Configuration
/// </summary>
public interface IMessagingConfiguration
{
/// <summary>
/// The OpenConnectionTimeout attribute specifies the timeout before a connection open is assumed to have failed
/// </summary>
TimeSpan OpenConnectionTimeout { get; set; }
/// <summary>
/// The ResponseTimeout attribute specifies the default timeout before a request is assumed to have failed.
/// </summary>
Expand Down Expand Up @@ -92,6 +96,7 @@ public interface IMessagingConfiguration
[Serializable]
public class MessagingConfiguration : IMessagingConfiguration
{
public TimeSpan OpenConnectionTimeout { get; set; }
public TimeSpan ResponseTimeout { get; set; }
public int MaxResendCount { get; set; }
public bool ResendOnTimeout { get; set; }
Expand Down Expand Up @@ -138,6 +143,7 @@ internal MessagingConfiguration(bool isSilo)
{
isSiloConfig = isSilo;

OpenConnectionTimeout = Constants.DEFAULT_OPENCONNECTION_TIMEOUT;
ResponseTimeout = Constants.DEFAULT_RESPONSE_TIMEOUT;
MaxResendCount = 0;
ResendOnTimeout = DEFAULT_RESEND_ON_TIMEOUT;
Expand Down
6 changes: 3 additions & 3 deletions src/Orleans/Messaging/GatewayConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,16 @@ public void Connect()
}
lastConnect = DateTime.UtcNow;
Socket = new Socket(Silo.Endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
Socket.Connect(Silo.Endpoint);
SocketManager.Connect(Socket, Silo.Endpoint, MsgCenter.MessagingConfiguration.OpenConnectionTimeout);
NetworkingStatisticsGroup.OnOpenedGatewayDuplexSocket();
MsgCenter.OnGatewayConnectionOpen();
SocketManager.WriteConnectionPreamble(Socket, MsgCenter.ClientId); // Identifies this client
Log.Info(ErrorCode.ProxyClient_Connected, "Connected to gateway at address {0} on trial {1}.", Address, i);
return;
}
catch (Exception)
catch (Exception ex)
{
Log.Warn(ErrorCode.ProxyClient_CannotConnect, "Unable to connect to gateway at address {0} on trial {1}.", Address, i);
Log.Warn(ErrorCode.ProxyClient_CannotConnect, $"Unable to connect to gateway at address {Address} on trial {i} (Exception: {ex.Message})");
MarkAsDisconnected(Socket);
}
}
Expand Down
27 changes: 26 additions & 1 deletion src/Orleans/Messaging/SocketManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,21 @@
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Orleans.Runtime.Configuration;

namespace Orleans.Runtime
{
internal class SocketManager
{
private readonly LRU<IPEndPoint, Socket> cache;
private TimeSpan connectionTimeout;

private const int MAX_SOCKETS = 200;

internal SocketManager(IMessagingConfiguration config)
{
connectionTimeout = config.OpenConnectionTimeout;
cache = new LRU<IPEndPoint, Socket>(MAX_SOCKETS, config.MaxSocketAge, SendingSocketCreator);
cache.RaiseFlushEvent += FlushHandler;
}
Expand Down Expand Up @@ -60,7 +63,7 @@ private Socket SendingSocketCreator(IPEndPoint target)
var s = new Socket(target.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
s.Connect(target);
Connect(s, target, connectionTimeout);
// Prep the socket so it will reset on close and won't Nagle
s.LingerState = new LingerOption(true, 0);
s.NoDelay = true;
Expand Down Expand Up @@ -171,6 +174,28 @@ internal void Stop()
cache.Clear();
}

/// <summary>
/// Connect the socket to the target endpoint
/// </summary>
/// <param name="s">The socket</param>
/// <param name="endPoint">The target endpoint</param>
/// <param name="connectionTimeout">The timeout value to use when opening the connection</param>
/// <exception cref="TimeoutException">When the connection could not be established in time</exception>
internal static void Connect(Socket s, IPEndPoint endPoint, TimeSpan connectionTimeout)
{
var signal = new AutoResetEvent(false);
var e = new SocketAsyncEventArgs();
e.RemoteEndPoint = endPoint;
e.Completed += (sender, eventArgs) => signal.Set();
s.ConnectAsync(e);

if (!signal.WaitOne(connectionTimeout))
throw new TimeoutException($"Connection to {endPoint} could not be established in {connectionTimeout}");

if (e.SocketError != SocketError.Success || !s.Connected)
throw new OrleansException($"Could not connect to {endPoint}: {e.SocketError}");
}

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
internal static void CloseSocket(Socket s)
{
Expand Down
4 changes: 3 additions & 1 deletion src/Orleans/Runtime/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ internal class Constants
public static readonly GrainId SiloDirectConnectionId = GrainId.GetSystemGrainId(new Guid("01111111-1111-1111-1111-111111111111"));

internal const long ReminderTableGrainId = 12345;


public static TimeSpan DEFAULT_OPENCONNECTION_TIMEOUT = TimeSpan.FromSeconds(5);

/// <summary>
/// The default timeout before a request is assumed to have failed.
/// </summary>
Expand Down