【发布时间】:2014-09-09 10:16:31
【问题描述】:
我们正在运行的网站有大约 15.000 个实时用户(谷歌分析)(大约 1000 个请求/秒(性能计数器))。
我们在负载均衡器后面有两个 Web 服务器。
有时每天有时每周 1 次我们的 Web 服务器之一停止执行请求并开始响应错误,并且每个请求都记录以下异常: “System.IndexOutOfRangeException - 索引超出了数组的范围。”
我们的环境:IIS 8.5、.Net 4.5.0、Mvc 5.1.0、Unity 3.5(与 3.0 状态相同)、WebActivatorEx 2.0 在 IIS 中,工作进程 1 和其他设置均采用默认设置。
我们无法捕捉到任何导致此错误的特定场景。应用程序池回收后一切都没有问题。并且在每个请求都以错误响应之前,没有任何与之相关的错误。
过去曾问过一个与相关旧 Unity 版本相关的问题: https://unity.codeplex.com/discussions/328841 http://unity.codeplex.com/workitem/11791 看不到我能做的任何事情。
这里的异常详情:
System.IndexOutOfRangeException
Index was outside the bounds of the array.
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at System.Linq.Enumerable.WhereListIterator`1.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Microsoft.Practices.Unity.NamedTypesRegistry.RegisterType(Type t, String name)
at Microsoft.Practices.Unity.UnityDefaultBehaviorExtension.OnRegisterInstance(Object sender, RegisterInstanceEventArgs e)
at System.EventHandler`1.Invoke(Object sender, TEventArgs e)
at Microsoft.Practices.Unity.UnityContainer.RegisterInstance(Type t, String name, Object instance, LifetimeManager lifetime)
at Microsoft.Practices.Unity.UnityContainerExtensions.RegisterInstance[TInterface](IUnityContainer container, TInterface instance, LifetimeManager lifetimeManager)
at DemoSite.News.Portal.UI.App_Start.UnityConfig.<>c__DisplayClass1.<RegisterTypes>b__0()
at DemoSite.News.Portal.Core.Controller.BaseController.Initialize(RequestContext requestContext)
at System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TState](AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
我的配置如下:
public static void RegisterTypes(IUnityContainer container)
{
var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
container.LoadConfiguration(section);
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));
}
初始化方法如下:
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
if (requestContext.RouteData.Values["ViewActionId"] != null)
{
int viewActionId;
if (!int.TryParse(requestContext.RouteData.Values["ViewActionId"].ToString(), out viewActionId))
return;
var cacheProvider = ServiceLocator.Current.GetInstance<ICacheProvider>();
List<ViewActionClass> viewActionClasses = null;
string cacheKey = CacheKeyCompute.ComputeCacheKey("ViewActionClass", CacheKeyTypes.DataCache,
new KeyValuePair<string, string>("viewActionId", viewActionId.ToString()));
_configuration = ServiceLocator.Current.GetInstance<IConfiguration>();
viewActionClasses =
cacheProvider.AddOrGetExistingWithLock<List<ViewActionClass>>(cacheKey, () =>
{
var viewActionClassBusiness =
ServiceLocator.Current.GetInstance<IViewActionClassBusiness>();
return viewActionClassBusiness.ViewActionClassGetByViewActionId(viewActionId);
});
ViewBag.ActionClass = viewActionClasses;
ViewBag.Configuration = _configuration;
}
base.Initialize(requestContext);
}
ICacheProvider、IConfiguration 和 IViewActionClassBusiness 的注册 xml
<type type="DemoSite.Runtime.Caching.ICacheProvider, DemoSite.Core"
mapTo="DemoSite.Runtime.Caching.ObjectCacheProvider, DemoSite.Core">
<lifetime type="containerControlledLifetimeManager" />
</type>
<type type="DemoSite.Core.Configuration.IConfiguration, DemoSite.Core"
mapTo="DemoSite.Core.Configuration.ConfigFileConfiguration, DemoSite.Core">
<lifetime type="containerControlledLifetimeManager" />
</type>
<type type="DemoSite.News.Business.IViewActionClassBusiness, DemoSite.News.Business"
mapTo="DemoSite.News.Business.Default.ViewActionClassBusiness, DemoSite.News.Business.Default">
<lifetime type="perRequestLifetimeManager" />
</type>
可能与高流量有关。 有没有人遇到过这样的问题以及解决办法?
提前致谢
【问题讨论】:
-
Csn你贴出匿名方法
App_Start.UnityConfig.<>c__DisplayClass1.<RegisterTypes>b__0()的代码?UnityConfig类中可能有一个RegisterTypes方法。该方法包含调用RegisterInstance的 lambda。 -
当您从 nuget 安装 Unity 引导程序时,我们使用相同的代码: public static void RegisterTypes(IUnityContainer container) { // 注意:要从 web.config 加载,请取消注释下面的行。确保将 Microsoft.Practices.Unity.Configuration 添加到 using 语句。容器.LoadConfiguration(); // TODO:在此处注册您的类型 // container.RegisterType
(); } --> nuget.org/packages/Unity.Mvc -
您查看的源代码是否与生产环境中运行的源代码不同?
App_Start.UnityConfig在某处包含一个被调用的匿名方法,但您显示的RegisterTypes方法不包含 lambda。 -
我会检查并通知您。另一件事是 ServiceLocator 有使用警告。它很旧,但有关于传递容器实例的警告:blogs.msdn.com/b/miah/archive/2009/05/12/… 并且在 UnityWebActivator 容器中传递了湖:DependencyResolver.SetResolver(new UnityDependencyResolver(container));
-
@Steven,感谢您的帮助。我们停止使用 ServiceLocator for Mvc。
标签: asp.net-mvc dependency-injection inversion-of-control unity-container ioc-container