Autofac踩坑经历
背景
接口框架使用反射,动态生成Controller
,使用Autofac
进行依赖注入,并替换默认DependencyResolver
及IControllerFactory
,Controller
实例化代码如下
//创建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>();
}
总结
- 这些使用官网文档里面都有提到,所以第三方组件使用一定要仔细阅读文档。
- 虽然官网给出解决方案,但我觉得这种方式有点别扭,对生命周期可能会产生影响。所以我觉得底层应该加上自动释放的机制。