Improve tracking of connection lifetime (#2646)

This commit is contained in:
Stephen Halter 2018-06-15 11:10:38 -07:00 committed by GitHub
parent 35d9590f3c
commit 14f020cf11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 24 deletions

View File

@ -11,7 +11,6 @@ using System.Net;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal; using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
@ -30,6 +29,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
private readonly HttpConnectionContext _context; private readonly HttpConnectionContext _context;
private readonly TaskCompletionSource<object> _socketClosedTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously); private readonly TaskCompletionSource<object> _socketClosedTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
private readonly TaskCompletionSource<object> _lifetimeTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
private IList<IAdaptedConnection> _adaptedConnections; private IList<IAdaptedConnection> _adaptedConnections;
private IDuplexPipe _adaptedTransport; private IDuplexPipe _adaptedTransport;
@ -53,8 +53,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
private int _writeTimingWrites; private int _writeTimingWrites;
private long _writeTimingTimeoutTimestamp; private long _writeTimingTimeoutTimestamp;
private Task _lifetimeTask;
public HttpConnection(HttpConnectionContext context) public HttpConnection(HttpConnectionContext context)
{ {
_context = context; _context = context;
@ -98,12 +96,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
private IKestrelTrace Log => _context.ServiceContext.Log; private IKestrelTrace Log => _context.ServiceContext.Log;
public Task StartRequestProcessing<TContext>(IHttpApplication<TContext> application) public async Task ProcessRequestsAsync<TContext>(IHttpApplication<TContext> httpApplication)
{
return _lifetimeTask = ProcessRequestsAsync(application);
}
private async Task ProcessRequestsAsync<TContext>(IHttpApplication<TContext> httpApplication)
{ {
try try
{ {
@ -132,9 +125,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
_adaptedTransport = adaptedPipeline; _adaptedTransport = adaptedPipeline;
} }
// Do this before the first await so we don't yield control to the transport until we've
// added the connection to the connection manager
_context.ServiceContext.ConnectionManager.AddConnection(_context.HttpConnectionId, this);
_lastTimestamp = _context.ServiceContext.SystemClock.UtcNow.Ticks; _lastTimestamp = _context.ServiceContext.SystemClock.UtcNow.Ticks;
_context.ConnectionFeatures.Set<IConnectionTimeoutFeature>(this); _context.ConnectionFeatures.Set<IConnectionTimeoutFeature>(this);
@ -194,7 +184,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
} }
finally finally
{ {
_context.ServiceContext.ConnectionManager.RemoveConnection(_context.HttpConnectionId);
DisposeAdaptedConnections(); DisposeAdaptedConnections();
if (_http1Connection?.IsUpgraded == true) if (_http1Connection?.IsUpgraded == true)
@ -204,6 +193,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
Log.ConnectionStop(ConnectionId); Log.ConnectionStop(ConnectionId);
KestrelEventSource.Log.ConnectionStop(this); KestrelEventSource.Log.ConnectionStop(this);
_lifetimeTcs.SetResult(null);
} }
} }
@ -269,7 +260,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
} }
} }
return _lifetimeTask; return _lifetimeTcs.Task;
} }
public void OnInputOrOutputCompleted() public void OnInputOrOutputCompleted()

View File

@ -73,22 +73,30 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
} }
var connection = new HttpConnection(httpConnectionContext); var connection = new HttpConnection(httpConnectionContext);
_serviceContext.ConnectionManager.AddConnection(httpConnectionId, connection);
var processingTask = connection.StartRequestProcessing(_application); try
{
var processingTask = connection.ProcessRequestsAsync(_application);
connectionContext.Transport.Input.OnWriterCompleted( connectionContext.Transport.Input.OnWriterCompleted(
(_, state) => ((HttpConnection)state).OnInputOrOutputCompleted(), (_, state) => ((HttpConnection)state).OnInputOrOutputCompleted(),
connection); connection);
connectionContext.Transport.Output.OnReaderCompleted( connectionContext.Transport.Output.OnReaderCompleted(
(_, state) => ((HttpConnection)state).OnInputOrOutputCompleted(), (_, state) => ((HttpConnection)state).OnInputOrOutputCompleted(),
connection); connection);
await AsTask(lifetimeFeature.ConnectionClosed); await AsTask(lifetimeFeature.ConnectionClosed);
connection.OnConnectionClosed(); connection.OnConnectionClosed();
await processingTask; await processingTask;
}
finally
{
_serviceContext.ConnectionManager.RemoveConnection(httpConnectionId);
}
} }
private Task AsTask(CancellationToken token) private Task AsTask(CancellationToken token)