WildFly 10 HA deploy: not losing sessions - session

I have been reading posts and documentation all day long about that topic, and still can't find something easy to understand and trust on.
I currently have my webapp deployed on WildFly 10, as a simple war file.
It's an e-commerce website, in production for a few weeks, and every time we need to deploy a new release, well... that's very annoying, because some customers could be shopping right now, and deployment will obviously make them lose their sessions, and that's very bad.
I need a solution to deploy a new war without restarting the application server. At first, I read the docs about clustering (domain configuration over standalone configuration), but I'm not sure that's enough for me...
Imagine the same customer with a few items in the shopping cart (http session), accessing the first node of the cluster.
Then I put it down, because I'm deploying.
OK, the customer will be redirected to the second node of the cluster but... will the session data still be available? Will he 'lose' the shopping cart items?
I read about sticky sessions, but nothing about configuring them in WildFly. I am on Amazon AWS, so I can use ELB (load balancer), too.
Can you help me understand exactly what I need to learn and use?

Each WildFly instance will have it's own session id that it keeps in the cookie. This id will only restore the session on the particular node it came from.
Sticky sessions mean that the ELB will always redirect the user to the same node in your cluster so that won't quite solve your problem.
Some things to think about:
Clustering
Clustering may help (doesn't need to be domain mode). With HA enabled, the session will be transferred between the nodes automatically so that cookie on the clients browser will be able to restore the session on either node. This of course has the issue where if you upgrade one of the war files first you may have an object that can no longer be de-serialized because it changed.
Clustering WF on AWS is a little tricky as well because you can't use UDP broadcast to discover each other. We use a database connection to keep track of nodes and do clustering.
Roll your own
One option you could do is to roll your own solution to keep just the minimum amount of information on the client as required. Something like:
create a record in the database with a GUID.
set the GUID to a cookie
Save the items in their cart in the database based on the GUID
have a filter that checks for the GUID cookie and can restore their cart each time they hit the site.
I've used an approach like this for e-commerce apps in the past. It has another side effect that you now have the person's shopping cart saved in your database and it's easy to see exactly what people were interested in buying.
Use Tomcat parallel deployment
Does your application require a full app server? If it is just servlet based you could try using Tomcat and it's parallel deployment functionality. It allows you to deploy your new .war file on top of your old one. It will then keep serving old sessions to the old war but new sessions will go to the new war file.
Parallel deployment is very cool if your app is simple enough to be able to use tomcat.

Related

Is there a way to backup a Liberty server deployment in Bluemix?

I am deploying a packaged liberty server into Bluemix that contains my application.
I want to update my application but before I do so, I'm wondering what's the best way to backup what I have currently up and running? If my update is bad, I would like to restore the previous version of my app.
In other words, what is the best practice or recommended way to update a web application running on a Liberty server in Bluemix. Do I simply keep a backup of the zip I pushed to Bluemix and restore it if something goes wrong? Or is there management capability provided by Bluemix for backup and restore?
It's understood that manual backup of the pushed zip is an acceptable strategy. Additionally, I found the Bluemix documentation Blue-green deployments to be a reasonable solution, as it's a deployment technique that utilizes continuous delivery and allows clients to rollback their app in the case of any issues.
The Cloud Foundry article Using Blue-Green Deployment to Reduce Downtime and Risk succinctly explains the deployment steps (since Bluemix is based on Cloud Foundry, the steps are similar to the Example: Using the cf map-route command steps in the previously cited Bluemix documentation).
I agree with Ryan's recommendation to use the blue/green approach, though the term may be unfamiliar to those new to cloud server deployments. Martin Fowler summarizes the problem it addresses in BlueGreenDeployment:
One of the challenges with automating deployment is the cut-over
itself, taking software from the final stage of testing to live
production. You usually need to do this quickly in order to minimize
downtime. The blue-green deployment approach does this by ensuring you
have two production environments, as identical as possible. At any
time one of them, let's say blue for the example, is live. As you
prepare a new release of your software you do your final stage of
testing in the green environment. Once the software is working in the
green environment, you switch the router so that all incoming requests
go to the green environment - the blue one is now idle.
Solving this problem is one of the main benefits of PaaS.
That said, for historical context, it's worth noting this blue/green strategy isn't new to cloud computing. Allow me to elaborate on one of the "old" ways of handling this problem:
Let's assume I have a website hosted on a dedicated server, myexample.com. My public-facing server's IP address ("blue") would be represented in the DNS "#" entry or as a CNAME alias; another server ("green") would host the newer version of the application. To test the new application in a public-facing manner without impacting the live production environment, I simply update /etc/hosts to map the top-level domain name to the green server's IP address. For example:
129.42.208.183 www.myexample.com myexample.com
Once I flush the local DNS entries and close all browsers, all requests will be directed to the green pre-production environment. Once I've confirmed all works as expected, I update the DNS entry for the live environment (myexample.com in this case). Assuming the DNS has a reasonably short TTL value like 300 seconds, I update the A record value if by IP or CNAME record value if by alias and the change will be propagated to DNS servers in minutes. To confirm the propagation of the new DNS values, I comment out the aforementioned /etc/hosts change, flush the local DNS entries, then run traceroute. Assuming it correctly resolves locally, I perform a final double-check all is well in the rest of the world with the free online DNS checker (e.g., whatsmydns.net).
The above assumes an update to the public-facing content server (e.g., an Apache server connecting to a database or application server); the switch over from pre-production to production is more involved if the update applies to a central database or similar transactional data server. If it's not too disruptive for site visitors, I disable login and drop all active sessions, effectively rendering the site read-only. Then I go about updating the backend server in much the same manner as previously described, i.e., switching a pre-production green front end to reference a replication in the pre-production green backend, test, then when everything checks out, switch the green front end to blue and re-enable login. Voila.
The good news is that with Bluemix, the same strategy above applies, but is simplified since there's no need to fuss with DNS entries or separate servers.
Instead, you create two applications, one that is live ("blue") and one that is pre-production ("green"). Instead of changing your site's DNS entries and waiting for the update to propagate around the world, you can update your pre-production application (cf push Green pushes the new code to your pre-production application), test it with its own URL (Green.ng.mybluemix.net), and once you're confident it's production-ready, add the application to the routing table (cf map-route Green ng.mybluemix.net -n Blue), at which point both applications "blue" and "green" will receive incoming requests. You can then take the previous application version offline by unmapping it (cf unmap-route Blue ng.mybluemix.net -n Blue).
Site visitors will experience no service disruption and unlike the "old" way I outlined previously, the deployment team (a) won't have to bite their nails waiting for DNS entries to propagate around the world before knowing if something doesn't work and (b) can immediately revert to the previous known working production version if a serious problem is discovered post-deployment.
You should be using some sort of source control, such as Git or SVN. Bluemix is nicely integrated with IBM DevOps Services (IDS) which can leverage git or an external Github repo to manage your project. When you open your app's dashboard, you should see a link in the upper right-hand corner that says "ADD GIT". That will automatically create a git repo for your project in IDS.
Using an SCM tool, you can manage versions of your code with relative ease. IDS provides you with an ability to deploy directly to Bluemix as part of your build pipeline.
After you have your code managed as above, then you can think about green/blue deployments, etc. as recommended above.

Share Sessions in IIS Web Farm

We have Windows Server 2008 R2 with IIS on in a web farm environment. I initiate a Classic ASP session and every so often, when refreshing the page, it doesn't show but then comes back again.
I go to http://mainurl.com but have two boxes called http://devbox1.com and http://devbox2.com
I put the files onto one of the DEV boxes which replicates to the other one.
After some reading, I guess this is down to a "common" issue with sharing sessions across a web farm instance.
Could someone please help me how to resolve this please?
Update:
As it's not clear in my post. Do not use the Session.SessionID as the identifier for the cookie as this will change across environments (Microsoft recommend never to store the SessionID in a database).
Quote from MSDN Library - Session.SessionID
You should not use the SessionID property to generate primary key values for a database application. This is because if the Web server is restarted, some SessionID values may be the same as those generated before the server was stopped. Instead, you should use an auto-increment column data type, such as IDENTITY with Microsoft® SQL Server™ or COUNTER with Microsoft Access.
Instead use a self generated id value that you then store in your cookie and the database. This way your Session object can be re-created.
There seems to be some discussion about solution using a database. Just to clarify Classic ASP uses Session object stored in memory this means the minute you switch machines load balanced or otherwise you still lose the session.
Interesting article on the IIS.net forums about this topic - iis 7 Load balancing
Quote from Bill Staples (who at the time was Product Unit Manager, IIS)
One thing to consider, however, is what to do with any application / session state. Classic ASP stores session state in memory that only one process can access. As soon as you scale the sites onto more than one machine, you can no longer guarantee that each incoming request for a particular user session is landing on the same machine, which means the client may suddenly 'lose state' between requests. This is why we recommend that you not use the built-in session support in ASP for these kinds of scenario. Instead we recommend you use SQL or another database to store this kind of data.
My recommendation would be to store the Session in a database create a cookie on the client machine then use this cookie to identify the session from the database.
Cookies can be changed so I would still recommend you use secure cookies across an SSL secured website, especially if data is of a sensitive nature.
You should create sticky sessions while working with web farms because most likely you have load balanced system which under standard configuration will point traffic to the lowest loaded node. As result your users will loose session from time to time.
Ask your network admin team to look how to create sticky session for your particular load balancers and network configuration, they should know exactly what this means.Here is one of the examples what this is and how to configure it: http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/US_StickySessions.html. But once again it is depend on what you are using.
**** solution with cookies or database entries not the best way to handle this situation because once again depend on your web farm configuration IIS may simple reject any attempt to overwrite session ID which you have stored in database or if security is tight enough even refuse to connect to page while connecting to other node.

How to do Continuous Integration with a live website without affecting users?

I have implemented Continuous Integration using TFS Version Control and TFS Build 2010. The compiled website project gets dropped in a shared folder with a version number.
Now I have a very basic question and may be a stupid question. When we normally deploy a website project from VS 2010 to a webserver it uploads App_Offline.htm file to the website folder so no requests are served to the user. After publish is completed that App_Offline.htm file is removed. During that period of time users see outage.
If we use CI on a live website then how can we eliminate that outage which appears to a user. I believe the whole point of CI is that users get to see newer features and the site is never down.
How is this accomplished? If we deploy website project to root folder then existing users will be affected and that is certainly no advisable.
I wanted to know what is the recommended practice with VS2010, TFS2010 Build & Version Control.
There's no real foolproof method for this, service up-time is never 100%, that's why people usually define it in 'nines'
But, if you had multiple web servers (Backup, fail-over, mirror etc.), you could roll out the update across them, so that as you update some servers, others will still be online (albeit with the old version) to serve users.
In general, only some of the largest websites have to worry so meticulously about being down for a few short minutes, so make sure you're focusing your energy in the right place ; )
Regarding taking down the site for the shortest time possible, the only way I've seen this done successfully is using multiple sites - either load balancing, or 2 sites on the same machine + swapping host headers after the release/warm up. But in most cases it's not worth the effort, releases shouldn't take down the site for more than a few seconds in which time there should be relatively few requests. You're better off trying a few things you can do to help your users live through a site release.
Move session out of proc.
If the users session lives in the app pool it will be lost when a new version is released, change the config to move it into a session server or the database.
Specify a machine key for the website
Viewstate (and cookies?) are encrypted using a key that is generated when a site starts, if a site restarts due to a release any users filling out a form will receive a invalid viewstate exception on postback. (Note: this may have other security implications)

Amazon EC2 ELB directing load to other instances and session stores

If we scale up (add an instance to ELB), could we redirect some existing requests to the new instance. So that, The users that we force to a new server will be asked to login again
If we scale down (remove an instance from ELB), then all users from that server will automatically be redirected by ELB to other remaining servers. These user should not be aked to login again.
Is this possible (including the redirect of request)? How?
Any ideas are welcome but I presume this can be solved using a central session store. I just don't know how to implement it .
And what are the options in using a central session store? simpledb? redis? memcached?
Our application is just a simple web application hosted in apache. We have two instances of it added unto the Amazon ELB, and we are using PHP.
Any ELB php specific suggestions? when a scale down/up happens that no user-visible symptomps should be shown?
For the most part, this should be completely transparent to your end users without many changes on your end.
The biggest aspect to look at on your side will be ensuring that sessions are persisted / available through the addition / removal of instances.
You can do this by setting a cookie on the client (default behavior in session_start() and ensuring all of your web servers with PHP have the facility to obtain information about the session id.
Some people will use memcached to do this ... and there is native integration in PHP for sessions to be stored in memcached ...
There are quite a bunch of ways to have a centralized session management. Some of them are listed below:
DB:
http://ocklin.org/session_management_cluster.html
Memcache:
http://www.migrate2cloud.com/blog/how-to-configure-memcached-on-aws-ec2-a-starters-guide (make sure the hosts are able to connect without any problem),
http://www.dotdeb.org/2008/08/25/storing-your-php-sessions-using-memcached/
http://php.net/manual/en/memcached.sessions.php
Msession:
http://in.php.net/manual/en/ref.msession.php

Windows Centralized Configuration for third party applications?

We are looking at a standard way of configuring the various "endpoints" of our application. Our application is a distributed system with Windows Desktop applications, Windows Server "services" and databases.
We currently configure each piece using XML files. This is getting a little out of hands as we work with larger customers who can have dozens of Servers running our application and hundreds of desktop clients.
Can anyone recommend a Microsoft technology or a third party that would allow us to centralize all that configuration information and manage it in a one place for all our applications? Any changes would be "pushed" to the endpoint(s) that are interested.
For example, if we were to change the login for one of our database, we would make that change on the database, then reflect that change in our centralized system. Following that last step, any service that needs to connect to the database would be notified of the change (and potentially receive the new data). How and what each endpoint does with that information is outside the scope of the system.
Our primary business is not "Centralized Configuration Services". We are a GIS company that provides solutions for various utilities worldwide.
I've done a couple of things to give myself this functionality over the years. I build enterprise applicatons that may be distributed across many servers. I don't want to bury config settings in each services config file or each web server's web.config file. For application specific stuff I usually create an application settings table in the app's database. The table only has two fields. SettingName and SettingValue. I then write a web or wcf service whose sole function it is to retrieve these settings. I write a function called GetSetting where you pass "SettingName" and it returns SettingValue or an empty string if your setting is not found. This way I can store all application settings for all components of the application in one spot. Maintenance and troubleshooting for this is really easy, I'm not hunting through scads of config files spread across a dozen web and app servers.
For larger scale apps I might create a separate AppSettings database where I add a new field to my table mentioned above. ApplicationName. My web or wcf service for this approach has the same method call (GetSetting) only at this scope I pass ApplicationName and SettingName and it returns SettingValue or an empty string.
Doing either of these things allows you to centralize all app settings for any size application or IT shop. It has worked really well for us.
You could use RSS together with BitTorrent to distribute changes. See Wikipedia. It is not MS specific however, but should provide the flexibility you need - a configuration server holding the configuration and providing the feeds needed to configure the clients and possibly servers.
Any VCS through a secure channel?
For example, git through ssh (both available in cygwin).
I think the first step is to have the secure channel (if you want the push ability, pulling might be different).
As for managing the "versions" in different "branches", what's better than a version control system?
As it goes for the Microsoft requirement, well the Microsoft sofwares in that exists in that area would suck pretty bad in your case (as in not the best tool for the job).

Resources