背景

接口框架使用反射,动态生成Controller,使用Autofac进行依赖注入,并替换默认DependencyResolverIControllerFactoryController实例化代码如下

//创建controller
public IController CreateController(RequestContext requestContext, string controllerName)
{
try
{
string key = string.Format(ControllerKey + "Controller", requestContext.RouteData.Values["controller"]).ToLower();
var resolver = DependencyResolver.Current as AutofacDependencyResolver;
return resolver.GetServiceWithKey<IController>(key);
}
catch
{
return null;
}
}
//autofac resolver代码,container为IContainer
return container.ResolveKeyed<T>(key);

问题

上线没两天,却发现导致服务器内容只剩10%不到,dump内存,发现大量Controller没有被回收。

Aufofac.Core.Disposer中的引用未释放,每次请求获取到的Controller实例没有得到释放,导致内存越来越少。

但以前也有用到在数据库层和服务层的情况,并没有出现内存不回收的情况。

原因分析

查看源代码,发现这里面存的是所有IDisponse对象,以前使用的类都没有实现IDisponse,所有每次获取实例使用后,gc会自动回收。而在Autofac中,如果每次获取的对象不使用BeginLifeScope的话,Autofac则认为对象生命周期没结束,则不会去释放对象。

所以需要调整代码如下

using(var scope = container.BeginLifeScope())
{
scope.Resolve<T>();
}

总结

  1. 这些使用官网文档里面都有提到,所以第三方组件使用一定要仔细阅读文档。
  2. 虽然官网给出解决方案,但我觉得这种方式有点别扭,对生命周期可能会产生影响。所以我觉得底层应该加上自动释放的机制。
05-11 20:01