Implementing Failover and Load Balancing in DataSnap 2010
Here I am with another post about DataSnap 2010. This time we will to talk about HTTP Tunneling which allows you to implement redundant solutions like Failover and Load Balancing in DataSnap applications. Questions about this subject are very frequent and I will give you, as an example, an overview using Failover. After reading this post you will be able to understand how you can implement Failover in your DataSnap applications and then use that to implement other redundant solution, like Load Balancing.
When we started to think about application servers as part of our N-tier development we had many goals like centralized processes, business rules, hardware investments, updates, etc. When we think about a centralized process, we also need to think about redundancy, which is the duplication of critical components of a system with the intention of increasing reliability , usually via a backup or fail-safe.
Before Delphi 2010, failover or load balance was not easy to implement, but now it is another story.
DataSnap 2010 brings a feature named HTTP Tunneling which allow you to have control of the data sent and received between the client and the server. HTTP Tunneling communicates through the HTTP protocol. Thus, you have to use that for the communication between client and server, which is not a problem.
When you implement Load Balancing or Failover, it means you will need a middleware application to control things. This application will be responsible for receiving the data from the client application, analyzing it, and forwarding it to the appropriate Server.
Translating that to the DataSnap world, theclient application connects to the Failover Server which is our proxy and it will forward the connection to the appropriate DataSnap Server in case of the primary connection fail. This post will simulate a client application sending/receiving data, while at some point the main DataSnap Server will crash, and you will see the Failover Server redirecting the connection to a secondary DataSnap Server.
If you are looking to implement this solution in your current DataSnap project and worried about what changes are necessary to support that, don’t worry. You will only need two changes on the client application:
- Define HTTP as connection protocol in your SQL Connection
- Start to connect on the Failover Server and not directly in your DataSnap Server
Beside that you need to create your Failover Server, and you can use this demo code as a start.
The Failover Server needs two components, the DSHTTPService which represent your server and is connected to the DSHTTPServiceAuthenticationManager for the authentication process, only authorized users can connect on the server.
To enable the HTTP Tunneling feature will you need to implement the follow events the HTTP Service Tunnel Service, which are:
- DSHTTPService1.HttpServer.TunnelService.OnErrorOpenSession
- DSHTTPService1.HttpServer.TunnelService.OnErrorWriteSession
- DSHTTPService1.HttpServer.TunnelService.OnErrorReadSession
- DSHTTPService1.HttpServer.TunnelService.OnOpenSession
- DSHTTPService1.HttpServer.TunnelService.OnWriteSession
- DSHTTPService1.HttpServer.TunnelService.OnReadSession
- DSHTTPService1.HttpServer.TunnelService.OnCloseSession
These events are executed during the communication process. The event names explain what they do, and the sample used on this post implements all of them. The sample has a log which will help you to see what is happening during the communication.
In the case of the Failover solution, all the events need to be implemented. The events OnErrorXXX will be executed when something goes wrong. These events will allow you identify and decide what to do with the bytes transferred. I will focus on the event OnErrorOpenSession which will redirect the connection in case of error during the opening session.
The follow code implements a method named Redirect which is associated with the event OnErrorOpenSession. You can see how the session data is represented by parameters on this method, and how it includes everything you need to redirect the data.
In this sample we use the Session.UserFlag to control if the connection was already redirected.We are only allowing one redirection, and in case that the Sender parameter becomes anException, we will save the error message in our log. After that we created an instance of DBXProperties which has the new redirection server information. I’m using the same HostName and changed the port to 213, differentiating it from the other DataSnap Server on the same machine, for demo purposes.
After that just reopen the session passing the new properties as parameter and it’s done — that is all you need.
procedure TForm6.Redirect(Sender: TObject; Session: TDSTunnelSession; Content: TBytes; var Count: Integer); var DBXProperties: TDBXDatasnapProperties; Msg: String; begin if Sender is Exception then Msg := Exception(Sender).Message; Log('>>' + Msg); if Session.UserFlag = 1 then Raise Exception.Create('Backup session cannot be redirected once more.' + Msg); DBXProperties := TDBXDatasnapProperties.Create(nil); DBXProperties.Values[TDBXPropertyNames.DriverName] := 'Datasnap'; DBXProperties.Values[TDBXPropertyNames.HostName] := 'localhost'; DBXProperties.Values[TDBXPropertyNames.Port] := '213'; try try Session.Reopen(DBXProperties); Session.UserFlag := 1; Msg := 'Flow commuted to alternate resource.'; Log('>>' + Msg); except Raise Exception.Create(Msg + '. Commuting to alternate resource failed.'); end; finally DBXProperties.free; end; end;
In case you are want to run the sample code in your machine, here the steps you need for that.
The sample includes two projects: Failover Server and DataSnap Server. We will use DataExplorer as our client application. Using the follow steps you will be able to see the Failover Server in action.
- Open and execute the Failover server, the sample use HTTP protocol and port 8080
- Execute the DataSnap Server twice, one using port 211 and other one port 213. The server using the port 213 will work as the backup server
- Create a DataSnap alias in your Data Explorer, remembering to configure it to use HTTP as protocol and port 8080
- On the Stored Procedure node, find the method EchoString, pass the value Delphi 2010 as parameter and execute. The return value will be Delphi 2010 (Server 211)
- Close the DataSnap Server that runs on the port 211
- Repeat the step 4 and look the return value, which should be Delphi 2010 (Server 213)
- Now look the log on the Failover Server, you will see the exception error and the redirection log information
Also, I prepared a short video where I present how to execute this sample.
You can download the source code here
Estimado Andreano Lanusse:
Muy útil y bueno el articulo y el vídeo, y lo he resaltado en mi blog porque el área de datasnap me parece muy importante dentro de nuestros desarrollos como programadores.
Pero al hilo de esto quería dejarte un comentario:
Recientemente ha sido añadida por youtube una funcionalidad que permite que los vídeos sean subtitulados y traducidos de forma automática, sin que suponga una carga adicional para las personas que los editan. Esta nueva funcionalidad puede ayudar mucho a la comunidad hispana ya que aunque no sea la traducción 100 % perfecta con el tiempo se ira mejorando.
En el caso de tu video también he visto que esta disponible esta funcionalidad desde youtube, lo he estado probando por saber si era algo que pudiera ser aprovechado por la comunidad hispana, pero el problema es que no detecta correctamente el audio en ingles y el subtitulo que crea en ingles no tiene nada que ver con lo que dices. Y por lo tanto, si lo traduces a otro idioma mucho menos.
Te hago el comentario porque dicen que es relativamente fácil el ajuste de la captura de audio, es decir, modificar el texto que ha sido capturado en el vídeo, por el autor para que el subtitulo se muestre correcto y pueda ser traducido correctamente. Y quizás así pueda llegar a mas personas dentro de la comunidad hispana.
Atentamente, le envío un saludo,
Salvador
Hola Salvador, gracias por publicar en tu blog.
Yo voy traducir los posts y vídeos sobre DataSnap al español, solamente falta tiempo 🙂
Creo que mas algunos días ya tendré algunos listos.
Saludos,
Andreano
The source code doesn’t seem to have the failover demo included.
Les, it’s, download the zip file and check the Failover folder
I downloaded item 27391 from the link below your very helpful video that says “You can download the source code here.” The folders in the zip are ASPNETClient, ASPNTCLIENT – Delphi Prism 2010, ASPNTCLIENT – Delphi Prism 2011, Client, DSFilterEncrypt, HTTP, Output, SendRecFiles and Server. Doing a search in the resultant directory for the word “failover” results in only the zip file name: 27391_datasnap_2010_failover_samples.zip. I don’t think I could be overlooking it.
Les,
Please, download again the zip file and you will see the failover folder.
There’s a saying that the definition of insanity is doing the same thing a second time and expecting different results. I guess I will have to re-examine that idea. It’s there now. Thanks for the help.
Hi, i’m want to know, whether the Delphi XE heavyweight callback can be used with redundant connection like fail over or load balancing.
And how to use them? Thanks.
Hi Iwan,
You can use, but in case you need to redirect the connection and the server method need to notify the client, it will fail, so you will need to re-execute the server method.
When I try start example Failover (FailoverDemo.groupproj) in RAD XE I got message class TDSHTTServiceAuthenticationMahager not found
Hi Vlad,
It’s because the authentication component in XE changed, just drop the DSAuthenticationManager component and set the AuthenticationManager property and onAuthenticate event for the HTTPService component. It will work.
Dear Andreano Lanusse.
Can you translate your example code of Failover on C++ language (C++ Builder XE).
Thank you.
Hi @Lena,
Yes, but will need sometime for that, I’m very busy here 🙂
Hi Andreano, some questions:
1) how would you implement the case when the “Primary” server comes back on and it has to receive the requests again?
2) why is not possible to switch more tha once?
3) is there somewhere a code/tutorial/article that describes load balancing?
BR
Mirko
Hi Mirko,
1) I would implement some mechanism on the server to verify if the server is back
2) This is just a demo, you can change the code and switch many times you want to.
3) The Delphi documentation describe the DataSnap HTTP Tunneling, if you wanna something specific about load balancing I would recommend google 🙂
Hi Andreano
Is there any way to get Failover & Load Balancing to working on a Tcp/Ip connection ?
Thanks
Hi Chales,
On the Load Balance/Failover Server no, because this feature happen through the HTTP Tunneling, on the other side the connection from this server to the DataSnap Servers can be done through TCP/IP
Andreano, I was already able to solve my problem, the only change was to remove CloseBackupSession from ErrorWriteBackupSession and ErrorReadBackupSession, because the saved TBytesStream still needs to be used. And of course, don’t using the UserFlag to mark that it already was redirected.
I’ve tried using the example code delphi based client themselves, the results can run and tunneling can work well. when I create a client application using php, tunneling can not work, the parameters that are sent do not continue to use the unchanged get a DataSnap / tunnel, and there is a 500 internal server error message. Can you give an example of accessing using php so that tunneling can run as well as the client made with delphi?