Our current project at work is a new MVC web site that will use a WCF service primarily to access a 3rd party billing system via a web service as well as a small SQL database for user personalization. The WCF service uses nHibernate for the SQL database.
We'd like to implement some sort of web farm for load balancing as well as failover and maintenance. I'm trying to decide the best way to handle nHibernate's caching and database concurrency if there are multiple WCF services running.
Some scenarios I've been thinking about...
1) Multiple IIS servers, one WCF server. With this setup, the WCF server would be a single point of failure, but there would be no issues with nHibernate caching or database concurrency.
2) Multiple IIS servers, each with it's own WCF service. This removes a single point of failure, but now nHibernate on one machine would not know about database changes done by another machine.
Some solutions to number 2 would be to use an IStatelessSession so we're not doing any caching and nHibernate is always fetching directly from the database. This might be the most feasible as our personalization database has very few objects in it. I'm also considering a 2nd-level cache such as memcached or Velocity, but it may be overkill for this system.
I'm putting this out there to see if anyone has experience doing this sort of architecture and to get some ideas for a solution. Thanks!
am i missing something here, i don't see a problem with nhibernate on the webservers.
application cache would not be a problem as each nhibernate box would keep it's own cache which would be populate from the datastore. look at creating a table that can be monitored for reasons to do a cache refresh. we used to do this using using CacheDependency class in .net 2.0 that would detect changes to a column and then remove the relevant item from the cache. so if a user inserts a new product, the cache would be dropped and the next call to get the products would load the cache again. it's old but check out: http://msdn.microsoft.com/en-us/magazine/cc163955.aspx#S2 for the concept. cheers
I would suggest not doing caching until not doing caching becomes a problem. Your DB will do its own caching to save you searching for the same data repeatedly, so the only thing you have to worry about is data across the wire. Judging by your description, you're not going to have a problem there. If you ever get to a stage where you do, use a distributed cache - allowing your servers to cache separately will cause you bouncing data problems on refresh.
Related
I have a application that has been programmed with MVC/EF Code First. It does a lot of server side processing and is pretty resource intensive.
I know how to set up load balancing, but, I want to know if scaling an EF application is as simple as provisioning a new server, deploying the application and pointing to the DB cluster - or are there any issues I will face with regards to multiple EF applications hitting the same database server?
I can't seem to find any advice/guides for this and I am worrying I made the wrong choice by choosing EF over something simpler/more straight forward!
... issues ... regards to multiple EF applications hitting the same database server?
Rewind a bit to the fact that your application is an ASP .NET MVC based application. Having multiple instances of it is probably going to raise the spectre of state management.
MSDN has a pretty good introduction to why this is an issue:
HTTP is a stateless protocol. This means that a Web server treats each HTTP request for a page as an independent request. The server retains no knowledge of variable values that were used during previous requests. ASP.NET session state identifies requests from the same browser during a limited time window as a session, and provides a way to persist variable values for the duration of that session. By default, ASP.NET session state is enabled for all ASP.NET applications.
Alternatives to session state include the following:
Application state, which stores variables that can be accessed by all users of an ASP.NET application.
This point is an extremely common way of storing state, but breaks down when there's multiple instances of an application involved (the state is "visible" to only one of the instances).
Typically this is worked around by using either the StateServer or SQLServer value of SessionStateMode. The same article provides a pretty good summary of each option (emphasis mine).
StateServer mode, which stores session state in a separate process called the ASP.NET state service. This ensures that session state is preserved if the Web application is restarted and also makes session state available to multiple Web servers in a Web farm.
SQLServer mode stores session state in a SQL Server database. This ensures that session state is preserved if the Web application is restarted and also makes session state available to multiple Web servers in a Web farm.
If your application is stateless, this is a moot point.
I am worrying I made the wrong choice by choosing EF
As far as issues with multiple instances of your application accessing a database go, you're going to have issues with any sort of data access technology.
Here's the basic scenario: let's say your application sends welcome emails to users on a schedule.
Given the table Users:
UserId | Email | WelcomeLetterSent
-------+-----------------+------------------
1 | user#domain.com | 0
And some psuedo-code:
foreach (var user in _context.Users.Where(u => !u.WelcomeLetterSent))
{
SendEmailForUser(user);
user.WelcomeLetterSent = true;
}
_context.SaveChanges();
There's a race condition where both instance one and instance two of your application might simultaneously evaluate _context.Users.Where(...) before either of them has the chance to set WelcomeLetterSent = true and call SaveChanges. In this case, two welcome emails might get sent to each user instead of one.
Concurrency can be an insidious thing. There's a primer on managing concurrency with the Entity Framework over here, but this is only the tip of the iceberg.
The answer to your question? It depends on what your application does :)
On top of that, I ideally want to build some "extra" support applications that hook in to the same DB... and, I am just not sure how EF will handle multiple apps to the same DB....
If your application can tolerate multiple instances of itself accessing one database, then it's usually not a stretch to make these "support applications" play nicely. It's not much different whether the concurrency is from multiple instances of one application or multiple applications with one instance each.
I'm currently designing a new website built on MVC and I wonder what is the right way to manage state.
The state should contain the userId and some structs of the user info, and should be kept during the whole session of the user while he's logged in (across http requests)
The important criteria:
1) Support scalability
2) Performance
The easy way is to use the Session object, but it doesn't support scalability. If different requests during the session go through different IIS servers, the session won't be kept. Although I've heard of load balancing tools which route all requests of a single session through the same machine, I'm not sure that it's a good practice to rely on it (isn't it?)
Another option that I've read about, is keeping the state data in special state servers which are running a RAM DB (like Cassandra for Linux or Redis for Windows). But it seems to me an overkill at this stage of the development.
Do you have any other suggestions?
I would like to start with something simple at the moment, but keep the design ready for a more advanced solution at the future.
Any best practice or code/design suggestions will be appreciated.
Thanks,
Edi.
(1) Use Sql Server to Store Session State
(2) Use Memcached as a Session State Provider
(3) Cook up your own solution using Caching on an external caching provider: look into using something like the ServiceStack Caching Framework. Using this, you can use Redis, Memcached, Azure or AWS to handle caching.
Next, create a KeyFactory to handle generation of keys for specific items. The item keys would include the UserId (which you would always have from FormsAuthentication UserId (assuming that you are using FormsAuthentication). Then store any Session data for the user in the cache. Using this approach you are using Caching in place of Session, and the cache can be shared across multiple servers.
Note: you can have different approaches regarding clearing out the user's data whenever they begin a new session. Potential approaches include:
Include the user's session start dateTime in the cacheKey, and auto-expire entries when they are no longer fresh
Clear out all potential entries for a user when they begin a new session
If you are using .NET 4.5 and dependent on the type and amount of information you are keeping on users you may want to look at using claims to store information about the user. In .NET 4.5 all Principals inherit from ClaimsPrincipal. ClaimsPrincipal already uses claims to store the user name, roles and other information. You can create your own service to transform claims, which will allow you to add additional information to the Principal user.
In dev environment I am using the ASP.NET configuration tool in Visual Studio to create a few users for testing. As I movel closer to QA and Production, I'm wondering what is the best way for me to automate the creation of a large amount (1000's) of users after application deployment.
I have a csv with all the usernames and passwords, roles etc. and I wan't to avail of the encryption and password salting security that is built in. I do not want to manually "Register" all these users.
I'm just not sure if this is something I can do (or instruct a db admin to perform for me).
Does anyone know of a way to achieve this?
Any assistance would be greatly appreciated.
Regards
The simplest solution would be to set up a "CSV Upload" form. The CSV would be processed by an MVC action calling Membership.CreateUser in a loop.
Probably, the performance of this will be good enough.
There's a few ways that I know of approaching a batch processing problem on an ASP.NET site.
Because of the wonky way an ASP.NET site's application pool can get recycled, batch processing is usually done on an external process.
Windows service
One way is a separate windows service, which gets the new excel and pumps that data in, and has a timer which keeps going around. I've seen this used often, and it is quite a pain, because it takes extra work to make it easily deployable.
Update ASP.Net membership from windows service
CacheItem
Second way is to use CacheItems and their expiration timers to do batch processing, what you do is you define a cache object with a long timer, and when that expires and the Removed-callback gets called, you do your database work. This is good because it deploys with your ASP.NET site, and you have your code in one logical place.
https://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/
Workflow Foundation
Third way, is to make a workflow foundation service. That service gets a call from your ASP.NET site, which instantiates a WF service, that does some db work with your excel file, and then it goes into a while-loop with a delay of a month in it. This is good, because it is not tied to the lifespan of your ASP.NET application pool - you get more control, and this logic can be separated into a different IIS hosted WCF service.
http://msdn.microsoft.com/en-us/library/dd489452.aspx
Integrating with data is always a pain though, remember that the solution that gives you the least work and least chance of failure when deploying is the best solution.
My previous setup was a single web server and a single database server. I was using nhibernate 2nd level caching to cache stuff to avoid lots of calls going to the database. This has worked great as i was using this this assembly
nhibernate.caches.syscache
and added this code to turn on the second level caching (using the regular syscache provider):
return configuration
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<ApplicationMap>().Conventions.Add(typeof(Conventions)))
.ExposeConfiguration(
c => {
c.SetProperty("proxyfactory.factory_class", proxyFactory);
c.SetProperty("cache.provider_class", "NHibernate.Caches.SysCache.SysCacheProvider, NHibernate.Caches.SysCache");
c.SetProperty("cache.use_second_level_cache", "true");
c.SetProperty("cache.use_query_cache", "true");
c.SetProperty("expiration", "86400");
})
.BuildSessionFactory();
I have now migrated over to a new environment that has multiple webservers and i am trying to understand the implications of this (I still have a single db server).
Since the cache was being stored on the webserver before, now it would seem like i have 2 parallel caches on each webserver which themselves may not be in sync and may cause out of date updates, etc.
What is the best solution to get the benefits of the caching i had before but also take advantage of the resiliency of the web server load balancing that is provided with this new setup?
Ayende blogged about 2nd level cache usage in NHibernate. You will need to use a distributed cache in a web farm scenario. For example SysCache2 (which relies on ASP.NET cache and which could be configured to use a distributed provider) or MemCache. Here's an article illustrating how you could configure memcached.
Well i've used memcached and it works like a charm. You may have to tweak the size of the cache but other than that it's hassle-free.
Setup a memached node on each webserver node and maintain that configuration as you add up nodes
Greetings,
Windows Azure only supports SQL Azure Session State for multiple instances.
I'm thinking what whether storing the objects in session will boost any performance for given scenario below:
Scenario:
I've got MVC Application where it's header and footer are populated from DB. I've created ApplicationController which inherits from controller. This applicationcontroller in turn will be inherited by actual controllers such as Home/Account etc.
I'm thinking of loading all these footer/header value in to session and use the session object for any subsequent requests.
Does anyone know whether this will boost any performance? Only reason I'm asking is that SQL Azure Session would do the same thing i.e. query SQL Azure Session storage for each request?
Thanks.
I would say that right now the amount of performance improvement you get from one option over the other is pretty negligible. The only way to know for sure would be to create some test scenarios.
Having said that, App Fabric Caching is coming out of CTP in less than a month and includes a session provider. If you were willing to use it you'd have two options:
Use the App Fabric Caching session provider and the session technique you've described above and it should be faster than either of the SQL options
Use the cache directly to provide the header and footer information (you'll still need to keep the data in SQL, but you can populate the cache on demand when headers and footers are requested)