NServiceBus.Host, NGen and LoadFrom

本文关键字:and LoadFrom NGen Host NServiceBus | 更新日期: 2023-09-27 17:57:41

我们有一个"小型"NServiceBus应用程序,它使用十几个EF映射表和RabbitMQ作为通信介质。使用NServiceBus。主办应用程序的Exe启动大约需要26秒(调试版本和发布版本都需要,无论是否附加调试器)。

添加EndpointConfigurationType应用程序设置后,加载时间减少了2s。

所以我一直在研究这个问题,在第一个查询中,EF和它的各种生成例程花费了大约8-10秒。EF加载性能也可以通过对库进行NGen来增强。

然而,在NGen之后:建立库并启动NServiceBus。Host.exe,本机映像由默认的appdomain加载,但也由一个附加的appdomain(使用IL dll)加载,因此看起来它使用LoadFrom来加载依赖项。

有办法绕过这个吗?我们想使用NSB。Host.exe的windows服务功能(我们对重新实现这些功能不感兴趣)。此外,其他"IWantTo…"功能也很好,因为我们已经有几个(16?)端点在使用这些功能。

编辑:http://blogs.msdn.com/b/abhinaba/archive/2014/02/18/net-ngen-explicit-loads-and-load-context-promotion.aspx我的所有dll都和NServiceBus在同一个目录中。Host.exe,因此基于此,Fusion也应该加载本机dll。

edit2:这是一个"最小"的repo,没有所有的b&w,但它似乎可以在调试情况下工作。它在2秒内启动,而Nservicebus.host.exe 的启动时间为26秒

using NServiceBus;
using BABAR.Configuration;
using System;
using System.Collections.Generic;
using System.Reflection;
namespace BABAR.NGENHelper
{
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Starting: {0}", DateTime.Now.ToLongTimeString());
        StartNSB();
        Console.WriteLine("NSB started: {0}", DateTime.Now.ToLongTimeString());
    }
    private static void StartNSB()
    {
        // this ends up loading EF, in this case unnoticeable
        NServiceBus.Unicast.Transport.TransportConnectionString.Override(
            GetRabbitMQConnectionString);
        NServiceBus.SetLoggingLibrary.Log4Net(() => log4net.Config.XmlConfigurator.Configure());
        var semibus = Configure.With(GetNSBAssemblies())
                .DefaultBuilder()
                .DefineEndpointName("NGENHelper")
                .UseTransport<NServiceBus.RabbitMQ>()
                .PurgeOnStartup(false)
                .UnicastBus()
                .ImpersonateSender(false)
                .RunHandlersUnderIncomingPrincipal(false)
                .CustomConfigurationSource(new DefaultNServiceBusConfigurationSource())
                .MessageForwardingInCaseOfFault()
                .DisableTimeoutManager();
        var bus = semibus.CreateBus()
            .Start(() => Configure.Instance.ForInstallationOn<NServiceBus.Installation.Environments.Windows>()
                            .Install());
    }
    public static string GetRabbitMQConnectionString()
    {
        var nc = new Access().GetNode<NodeConfiguration>();
        return nc.RabbitConnectionString;
    }
    internal static IEnumerable<Assembly> GetNSBAssemblies()
    {
        return new[] { 
            typeof(NServiceBus.RabbitMQ).Assembly, // IConfigureTransport for NSB
            typeof(BABAR.Bootstrapper).Assembly, 
        };
    }
}
}

NServiceBus.Host, NGen and LoadFrom

我认为只使用自托管https://github.com/SimonCropp/NServiceBus.SelfHost#self-主机

请参阅下面的自主机示例代码

NSB主机的"服务功能"可以通过调用sc.exe来替代https://github.com/SimonCropp/NServiceBus.SelfHost#install--卸载

class ProgramService : ServiceBase
{
    IStartableBus bus;
    static void Main()
    {
        using (var service = new ProgramService())
        {
            // so we can run interactive from Visual Studio or as a service
            if (Environment.UserInteractive)
            {
                service.OnStart(null);
                Console.WriteLine("'r'nPress any key to stop program'r'n");
                Console.Read();
                service.OnStop();
            }
            else
            {
                Run(service);
            }
        }
    }
    protected override void OnStart(string[] args)
    {
        Configure.GetEndpointNameAction = () => "SelfHostSample";
        bus = Configure.With()
            .DefaultBuilder()
            .UnicastBus()
            .CreateBus();
        bus.Start(Startup);
    }
    static void Startup()
    {
        //Only create queues when a user is debugging
        if (Environment.UserInteractive && Debugger.IsAttached)
        {
            Configure.Instance.ForInstallationOn<Windows>().Install();
        }
    }
    protected override void OnStop()
    {
        if (bus != null)
        {
            bus.Shutdown();
        }
    }
}