南希开始慢慢接受请求
本文关键字:请求 慢慢 开始 | 更新日期: 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);
}
}