南希开始慢慢接受请求

本文关键字:请求 慢慢 开始 | 更新日期: 2023-09-27 17:58:26

我很难理解Nancy为什么在大约1分钟内不接受请求。我有大约60个端点,所有这些端点都很快初始化,所以所有模块都得到了处理。

这有共同的原因吗?或者有没有办法追踪到底发生了什么?

编辑

应用程序启动的日志记录

App Start 4/15/2014 11:03:48 AM
App Start Complete 4/15/2014 11:03:48 AM
Bootstrap 4/15/2014 11:04:19 AM
Module 3 4/15/2014 11:06:37 AM
Module 1 4/15/2014 11:06:37 AM
Module 2 4/15/2014 11:06:37 AM
Module 1 4/15/2014 11:06:37 AM
Module 1 4/15/2014 11:06:37 AM
Module 1 4/15/2014 11:06:37 AM
Module 1 4/15/2014 11:06:37 AM
Module 1 4/15/2014 11:06:37 AM
Module 1 4/15/2014 11:06:38 AM
Module 1 4/15/2014 11:06:38 AM
Module 1 4/15/2014 11:06:38 AM

从时间上可以看出,在引导之前以及在调用模块之前都有延迟。

编辑2

我的配置是Nancy(v0.22.2是从源代码构建的,因为需要强密钥,没有代码更改)使用Web Forms的ASP.NET 4.5。使用Visual Studio 2013作为IDE

南希开始慢慢接受请求

我想我发现了问题所在。问题出在Nancy使用的TinyoC容器中的"自动注册"功能上。

基本上在启动(第一次请求)时,它会扫描AppDomain的每个程序集以注册依赖项。这个过程非常缓慢:https://github.com/NancyFx/Nancy/issues/643

解决方案是手动注册依赖项,如下所示:https://github.com/NancyFx/Nancy/wiki/Bootstrapping-nancy

基本上,您只需要在AspNet项目中创建一个继承自DefaultNancyAspNetBootstrapper的类,并重写ConfigureApplicationContainer方法:

public class Bootstrapper : DefaultNancyAspNetBootstrapper
{
    protected override void ConfigureApplicationContainer(TinyIoCContainer container)
    {
        // Register our app dependency as a normal singleton           
    }
}

希望这有帮助,

Nancy中AutoRegister功能执行缓慢的根本原因是处理了大量的程序集和类型。第二个问题不是这种情况下的最佳代码。Nancy(1.4.3)的当前稳定版本具有以下代码https://github.com/NancyFx/Nancy/blob/1.x-WorkingBranch/src/Nancy/TinyIoc/TinyIoC.cs#L3092-13094因此,这个linq表达式针对每种类型进行了处理。。。要更改此行为,您可以使用以下类作为引导程序的基础。此外,您还可以通过在AutoRegisterIgnoredAssemblys中排除您的第三方程序集来加快此代码的速度(请参阅代码中的示例)。

在我的系统中,它有助于将自动注册的速度从50秒提高521倍到95毫秒。

    public class AutoRegistredBootstrapper : DefaultNancyBootstrapper
{
    private readonly object AutoRegisterLock = new object();
    private void AutoRegister(TinyIoCContainer container, IEnumerable<Assembly> assemblies)
    {
        var ignoreChecks = new List<Func<Type, bool>>()
        {
            t => t.FullName.StartsWith("System.", StringComparison.Ordinal),
            t => t.FullName.StartsWith("Microsoft.", StringComparison.Ordinal),
            t => t.IsPrimitive(),
            t => (t.GetConstructors(BindingFlags.Instance | BindingFlags.Public).Length == 0) && !(t.IsInterface() || t.IsAbstract()),
            t => t.Assembly == typeof(NancyEngine).Assembly
        };

        lock (AutoRegisterLock)
        {
            var thisType = this.GetType();
            var types = assemblies.SelectMany(a => AssemblyExtensions.SafeGetTypes(a))
                .Where(type => (type.DeclaringType != thisType)
                               && !type.IsGenericTypeDefinition())
                .Where(t => !ignoreChecks.Any(check => check(t)))
                .ToList();
            var assignebleTypes =
                types.Where(
                        type =>
                            type.IsClass() && (type.IsAbstract() == false) && (type != thisType))
                    .Select(t =>
                    {
                        // be careful with side effects in linq
                        container.Register(t);
                        return t;
                    })
                    .Where(implementationType => implementationType.GetTypeInfo().ImplementedInterfaces.Any() || implementationType.BaseType != typeof(Object))
                    .ToList();
            var abstractInterfaceTypes = types.Where(type => ((type.IsInterface() || type.IsAbstract())));
            foreach (var abstractInterfaceType in abstractInterfaceTypes)
            {
                var localType = abstractInterfaceType;
                var implementations =
                    assignebleTypes.Where(implementationType => localType.IsAssignableFrom(implementationType)).ToList();
                if (implementations.Count > 1)
                {
                    if (implementations.Count != implementations.Distinct().Count())
                    {
                        var fullNamesOfDuplicatedTypes = string.Join(",'n",
                            implementations.GroupBy(i => i).Where(j => j.Count() > 1).Select(j => j.Key.FullName));
                        throw new ArgumentException($"types: The same implementation type cannot be specified multiple times for {abstractInterfaceType.FullName}'n'n{fullNamesOfDuplicatedTypes}");
                    }
                    foreach (var implementationType in implementations)
                    {
                        container.Register(abstractInterfaceType, implementationType, implementationType.FullName);
                    }
                }
                var firstImplementation = implementations.FirstOrDefault();
                if (firstImplementation != null)
                {
                    container.Register(abstractInterfaceType, firstImplementation);
                }
            }
        }
    }
    protected override IEnumerable<Func<Assembly, bool>> AutoRegisterIgnoredAssemblies
    {
        get
        {
            return DefaultAutoRegisterIgnoredAssemblies.Concat(new Func<Assembly, bool>[]
            {
                asm => asm.FullName.StartsWith("ICSharpCode.", StringComparison.Ordinal),
                asm => asm.FullName.StartsWith("Ionic.", StringComparison.Ordinal),
                asm => asm.FullName.StartsWith("CommandLine,", StringComparison.Ordinal)
                // ADD THE REST OF 3D party libs that you don't use as dependencies 
            });
        }
    }
    protected override void ConfigureApplicationContainer(TinyIoCContainer container)
    {
        var currentDomainAssemblies = AppDomain.CurrentDomain.GetAssemblies();
        var ignoredAssemblies = this.AutoRegisterIgnoredAssemblies.ToList();
        var asmsForProcessing = currentDomainAssemblies.Where(a => !ignoredAssemblies.Any(ia => ia(a))).ToList();
        AutoRegister(container, asmsForProcessing);
    }
}