Implementing Failover and Load Balancing in DataSnap 2010

Let's share the knowledge with your friends

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.

  1. Open and execute the Failover server, the sample use HTTP protocol and port 8080
  2. 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
  3. Create a DataSnap alias in your Data Explorer, remembering to configure it to use HTTP as protocol and port 8080
  4. 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)
  5. Close the DataSnap Server that runs on the port 211
  6. Repeat the step 4 and look the return value, which should be Delphi 2010 (Server 213)
  7. 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


Let's share the knowledge with your friends
19 replies
  1. salvador jover
    salvador jover says:

    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

    Reply
  2. Andreano Lanusse
    Andreano Lanusse says:

    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

    Reply
  3. Les
    Les says:

    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.

    Reply
  4. Les
    Les says:

    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.

    Reply
  5. Iwan
    Iwan says:

    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.

    Reply
  6. Vlad
    Vlad says:

    When I try start example Failover (FailoverDemo.groupproj) in RAD XE I got message class TDSHTTServiceAuthenticationMahager not found

    Reply
    • Andreano Lanusse
      Andreano Lanusse says:

      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.

      Reply
  7. Lena
    Lena says:

    Dear Andreano Lanusse.
    Can you translate your example code of Failover on C++ language (C++ Builder XE).
    Thank you.

    Reply
  8. Mirko
    Mirko says:

    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

    Reply
    • Andreano Lanusse
      Andreano Lanusse says:

      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 🙂

      Reply
    • Andreano Lanusse
      Andreano Lanusse says:

      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

      Reply
  9. Walter
    Walter says:

    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.

    Reply
  10. rio alamanda
    rio alamanda says:

    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?

    Reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.