创建针对Linux Docker容器的长期运行的.NET Core服务

时间:2017-06-14 14:49:00

标签: c# docker .net-core

似乎有两种类型的实质性.NET Core项目:ASP.NET Core Web App和Console App。我想在Docker环境(Linux容器)中构建类似Windows服务的东西,其中进程启动,无限期运行,并且仅在被告知时停止。两种项目类型似乎都不合适。我错过了什么吗?

3 个答案:

答案 0 :(得分:4)

术语"控制台"可能在这里有点误导。微软使用它来区分它" GUI"应用程序(如WinForms,WPF,UWP,Xamarin等)或通过IIS引入的Web应用程序。 ASP.NET核心应用程序只是具有用于托管Web服务器的库的控制台应用程序。

因此,对于您的应用,一个"控制台"是您想要的项目类型。正如@mason所提到的,即使是Windows服务也只是" console"应用程序 - 不是GUI应用程序的.exe文件。

答案 1 :(得分:4)

这两种类型的应用程序都有意义,这取决于您计划如何与此服务进行通信。

如果您想在某些TCP端口上通过标准HTTP与之通信,那么使用ASP.Net核心Web应用程序将使事情变得更容易。

如果你想通过更多的东西进行交流"异国情调"像RabbitMQ,Kafka,原始TCP套接字或其他东西,然后控制台应用程序是你想要的。正如Gareth Luckett的回答指出的那样,诀窍就是确保你的main功能块。只要容器应该运行,运行的Docker容器就会阻止主线程阻塞。

答案 2 :(得分:2)

不幸的是,控制台应用程序在运行时需要stdin,通过docker它会立即退出。你可以托管'它使用asp.net。

public class Program
{
    public static ManualResetEventSlim Done = new ManualResetEventSlim(false);
    public static void Main(string[] args)
    {
        //This is unbelievably complex because .NET Core Console.ReadLine() does not block in a docker container...!
        var host = new WebHostBuilder().UseStartup(typeof(Startup)).Build();

        using (CancellationTokenSource cts = new CancellationTokenSource())
        {
            Action shutdown = () =>
            {
                if (!cts.IsCancellationRequested)
                {
                    Console.WriteLine("Application is shutting down...");
                    cts.Cancel();
                }

                Done.Wait();
            };

            Console.CancelKeyPress += (sender, eventArgs) =>
            {
                shutdown();
                // Don't terminate the process immediately, wait for the Main thread to exit gracefully.
                eventArgs.Cancel = true;
            };

            host.Run(cts.Token);
            Done.Set();
        }
    }      
}

Startup类:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IServer, ConsoleAppRunner>();
    }


    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    }
}

ConsoleAppRunner类

public class ConsoleAppRunner : IServer
{

    /// <summary>A collection of HTTP features of the server.</summary>
    public IFeatureCollection Features { get; }

    public ConsoleAppRunner(ILoggerFactory loggerFactory)
    {
        Features = new FeatureCollection();
    }

    /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
    public void Dispose()
    {

    }

    /// <summary>Start the server with an application.</summary>
    /// <param name="application">An instance of <see cref="T:Microsoft.AspNetCore.Hosting.Server.IHttpApplication`1" />.</param>
    /// <typeparam name="TContext">The context associated with the application.</typeparam>
    public void Start<TContext>(IHttpApplication<TContext> application)
    {
        //Actual program code starts here...
        Console.WriteLine("Demo app running...");

        Program.Done.Wait();        // <-- Keeps the program running - The Done property is a ManualResetEventSlim instance which gets set if someone terminates the program.

    }
}

来源:https://stackoverflow.com/a/40549512/2238275