问题
I have OWIN server as part of console app. You can see the main method here:
class Program
{
public static ManualResetEventSlim StopSwitch = new ManualResetEventSlim();
static void Main(string[] args)
{
Console.CancelKeyPress += (s, a) =>
{
a.Cancel = true;
StopSwitch.Set();
};
using (WebApp.Start<Startup>("http://+:8080/"))
{
Console.WriteLine("Server is running...");
Console.WriteLine("Press CTRL+C to stop it.");
StopSwitch.Wait();
Console.WriteLine("Server is stopping...");
}
Console.ReadKey();
Console.WriteLine("Server stopped. Press any key to close app...");
}
}
When processing of the request is little bit longer and in the same time user presses CTRL+C to stop the application the request processing is stopped immediately and response is not sent. Is it possible to change this behavior? I would like to refuse all new requests but wait until the requests which are currently processing are done and stop server after that.
My initial idea is to create OWIN middleware which will keep track of requests which are currently processing and postpone the stop action until everything is done. Middleware would also short-circuit all requests during the stopping phase. But this solution doesn't sound good to me.
回答1:
I ended with the suggested approach with the middleware:
public class ShutDownMiddleware
{
private readonly Func<IDictionary<string, object>, Task> next;
private static int requestCount = 0;
private static bool shutDownStateOn = false;
public static void ShutDown()
{
shutDownStateOn = true;
}
public static int GetRequestCount()
{
return requestCount;
}
public ShutDownMiddleware(Func<IDictionary<string, object>, Task> next)
{
this.next = next;
}
public async Task Invoke(IDictionary<string, object> environment)
{
if (shutDownStateOn)
{
environment["owin.ResponseStatusCode"] = HttpStatusCode.ServiceUnavailable;
return;
}
Interlocked.Increment(ref requestCount);
try
{
await next.Invoke(environment);
}
finally
{
Interlocked.Decrement(ref requestCount);
}
}
}
This is registered as a first middleware in the pipeline and in the main method of program I can use it like this:
public class Program
{
public static ManualResetEventSlim StopSwitch = new ManualResetEventSlim();
static void Main(string[] args)
{
Console.CancelKeyPress += (s, a) =>
{
a.Cancel = true;
StopSwitch.Set();
};
using (WebApp.Start<Startup>("http://+:8080/"))
{
Console.WriteLine("Server is running...");
Console.WriteLine("Press CTRL+C to stop it.");
StopSwitch.Wait();
Console.WriteLine("Server is stopping...");
ShutDownMiddleware.ShutDown();
while (ShutDownMiddleware.GetRequestCount() != 0)
{
Thread.Sleep(TimeSpan.FromSeconds(1));
}
}
}
}
I also found this: https://katanaproject.codeplex.com/workitem/281 They are talking about similar approach.
来源:https://stackoverflow.com/questions/26012227/finish-current-requests-when-stopping-self-hosted-owin-server