Hi Kendall
There are three things that have an influence on the instance returned to you:
1. The same binding must be used to resolve an instance. If you have conditional bindings for a type they will return different instances even when having the same scope.
2. The scope. Since you have a custom scope but didn’t provide any code, it is impossible to tell if you have implemented them correctly. You have to know that the instance that you return here decides which cached object will be returned. And that they are kept in the cache until the scope object is GC’d. In a high load environment is might be necessary to actively tell Ninject to remove objects cached by some scope. E.g. when using request scope we actively tell Ninject to remove the objects in this request after the request is completed. Otherwise you can get out of memory exceptions because the GC loop takes too long. Also be aware that your scope implementation must be thread safe. Ninject will access it concurrently from all threads that you use to resolve objects.
3. The object must be resolved from the same kernel instance. Depending on your implementation you are either using one shared kernel or one for each app pool instance. In the second case the resolved objects are per app pool instance and you cannot expect to reuse them between app pools
Probably you should add code to show how you implemented your scope. I think there is a high change that the problem is in there.
Btw, caching is done in the cache: https://github.com/ninject/ninject/blob/master/src/Ninject/Activation/Caching/Cache.cs
Remo
--
You received this message because you are subscribed to the Google Groups "ninject" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ninject+u...@googlegroups.com.
To post to this group, send email to nin...@googlegroups.com.
Visit this group at http://groups.google.com/group/ninject.
For more options, visit https://groups.google.com/groups/opt_out.
There are three things that have an influence on the instance returned to you:1. The same binding must be used to resolve an instance. If you have conditional bindings for a type they will return different instances even when having the same scope.
2. The scope. Since you have a custom scope but didn’t provide any code, it is impossible to tell if you have implemented them correctly. You have to know that the instance that you return here decides which cached object will be returned.
And that they are kept in the cache until the scope object is GC’d. In a high load environment is might be necessary to actively tell Ninject to remove objects cached by some scope. E.g. when using request scope we actively tell Ninject to remove the objects in this request after the request is completed. Otherwise you can get out of memory exceptions because the GC loop takes too long. Also be aware that your scope implementation must be thread safe. Ninject will access it concurrently from all threads that you use to resolve objects.
3. The object must be resolved from the same kernel instance. Depending on your implementation you are either using one shared kernel or one for each app pool instance. In the second case the resolved objects are per app pool instance and you cannot expect to reuse them between app pools
Probably you should add code to show how you implemented your scope. I think there is a high change that the problem is in there.Btw, caching is done in the cache: https://github.com/ninject/ninject/blob/master/src/Ninject/Activation/Caching/Cache.csRemo
From: nin...@googlegroups.com [mailto:ninject@googlegroups.com] On Behalf Of Kendall Bennett
Sent: Montag, 15. Juli 2013 23:47
To: nin...@googlegroups.com
Subject: [ninject] Ninject failures under high load with ASP.NET MVC?
Hi Guys,
We have been battling some really odd bugs in our system when under high load for some time, but never could track it down. Then recently we made some changes that caused Ninject to be used more heavily and earlier in the request pipeline on our web site, and immediately started to see some odd crashes, which when we examined the issue looked clearly like threading issues. Two threads were executing on the same Ninject resolved instance, which should never happen. We searched high and low, but never could find any issues in our code, and it finally led me to start to suspect Ninject. No matter what we do, we cannot reproduce the issue in a debug environment, and even on our staging server we had to heavily load the machine using Telerik Test Studio before we finally managed to have it fail in the same way that our live server does. We have been able to work around the crash issues in the code by putting threading locks in place, but it is only a stop gap measure, not a proper solution. And on our live server the issue only appears to happen once every couple of hours, or when the application pool is recycled. It seems to happen a lot more regularly when the load on the server is going up or down, indicating that new scope objects are getting created or destroyed.
We also updated Ninject from the 2.2 release we were using, to the latest stable release in NuGet (3.0.2 or something). It made no difference.
Near as I can figure out, when under load, Ninject sometimes serves up the WRONG instance to us, like it has scoped it wrong or something. We do not currently use request scope, but rather use application scope, which is a custom scope we made ourselves to bind the Ninject instances to instances of HttpApplication under ASP.NET. Since ASP.NET ensures that only one request at a time can be handled by a single application instance, it means we can avoid having to deal with threading issues within our code, and code it liked it is single threaded, as each application instance should end up getting their own set of objects, scoped to that application instance. More importantly, the instances remain across requests so we can cache things internally as necessary between requests for better performance. In our code we put some checks in to see if the application instance stored in the object Ninject returns to us is DIFFERENT to the current application instance, and then we log it. This happens every couple of hours, at the same time that we were normally seeing the crashes. So clearly Ninject at some point is giving us objects for the WRONG application instance, and it only happens under load. Which would indicate there is probably some kind of threading issue within the Ninject kernel (since it is a singleton instance used throughout the entire app).
Has anyone noticed anything similar before? I spoke briefly with the folks at Mindscape about the issues, as we have been using their new RayGun.IO project to capture the runtime errors and log information about the issues, and they mentioned they gave up using Ninject as they had seen some similar issues in the past and never worked it out. This is what he said:
"I can't help explicitly with your issue here but I will say that we've used Ninject several times and have run into the problem that it never disposes things properly -- even when using the InstancePerRequest model (or something like that -- it was a long time ago). What would happen is that you'dexpect it to therefore give you clean items per request but in fact it wouldn't -- it would re-use them globally. This caused us a lot of issues until we figured out that it wasn't doing what you'd think.
It's a random comment but perhaps that's what is happening for you also? It's the sort of issue that only appeared for us once under load as well - on a dev machine or similar low load machine it was difficult to create weirdness."
Not sure if that was related to this or not, but now I am 99.9% sure something is wrong with Ninject. I plan to try using a different IoC container and see if it makes any difference, but I would really like to know if anyone else has seen anything similar to this, and if you have any suggestions on where I can look in the code to see where it might be going wrong?
Unfortunately because we cannot reproduce this problem in a debug environment, and only in a non-debug environment under load, it is really difficult to actually setup up a debug version of Ninject and try to follow the code through and figure out where it might be going wrong. But if someone can point out where in the code it does the scoping stuff, I could follow it through and see if I can spot anything.
BTW, the machine is running Windows Server 2008 R2, 64-bit, ASP.NET 4.5, .NET 4.5, ASP.NET MVC 4.
- Kendall
--
You received this message because you are subscribed to the Google Groups "ninject" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ninject+u...@googlegroups.com.
To post to this group, send email to nin...@googlegroups.com.
Visit this group at http://groups.google.com/group/ninject.
For more options, visit https://groups.google.com/groups/opt_out.
--
You received this message because you are subscribed to a topic in the Google Groups "ninject" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ninject/SEVZ8SUnAOo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ninject+u...@googlegroups.com.
To post to this group, send email to nin...@googlegroups.com.
Visit this group at http://groups.google.com/group/ninject.
For more options, visit https://groups.google.com/groups/opt_out.
1.
By the same binding I mean that if there are two conditional bindings they will not return the same instance e.g.
Bind<IFoo>().To<Foo>().When(c => DateTime.Now.Hour % 2 == 0).InSingletonScope()
Bind<IFoo>().To<Foo>().When(c => DateTime.Now.Hour % 2 == 1).InSingletonScope()
Will create two instances of Foo.
2.
I don’t’ know when IIS creates a new HttpContext.Current.ApplicationInstance Instance and when it reuses an existing one. Probably you should verify that it has the lifetime that you expect. E.g. is it the same instance after an App Pool recycling or does it just contain the same data but it is a different instance?
You can mix scope. But you have to make sure that no object uses another with shorter lifetime. E.g. it is a bad idea to inject a request scoped object instance into a singleton/application scoped object instance.
BTW request Scope still exists it just has been moved into the Web extensions so that the core doesn’t depend on System.Web anymore.
I'm not sure I have a lot to contribute but perhaps I can throw some relevant questions in that may help.Out of curiosity, is there a major reason why you have to manage your own scoping? I've found that ninject 3 and up is pretty rock solid as far as using the scope management that's baked in, but perhaps you need that level of wiring for your application.
When you mentioned that using request scope on your live server completely looks everything up, We use a mix of request/application scope in all our production apps and have never experienced anything like this.
As far as iis config, you mentioned you have multiple applications use the same app pool. I would star by separating these out because it proves for an easy way to determine in exactly which app the problem resides when you can easily pinpoint production problems.
I'm curious as to what the problem is here as I haven't experienced behavior out of ninject like this before. If you find the problem can you update the thread to help my curiosity?
1.By the same binding I mean that if there are two conditional bindings they will not return the same instance e.g.Bind<IFoo>().To<Foo>().When(c => DateTime.Now.Hour % 2 == 0).InSingletonScope()Bind<IFoo>().To<Foo>().When(c => DateTime.Now.Hour % 2 == 1).InSingletonScope()Will create two instances of Foo.
2.I don’t’ know when IIS creates a new HttpContext.Current.ApplicationInstance Instance and when it reuses an existing one. Probably you should verify that it has the lifetime that you expect. E.g. is it the same instance after an App Pool recycling or does it just contain the same data but it is a different instance?
You can mix scope. But you have to make sure that no object uses another with shorter lifetime. E.g. it is a bad idea to inject a request scoped object instance into a singleton/application scoped object instance.
BTW request Scope still exists it just has been moved into the Web extensions so that the core doesn’t depend on System.Web anymore.