Using Delphi and RO 9.x in order to create a fail over solution.
After testing a simple server (hooking all components at runtime), I am now trying to add a failover procedure using TRoServerLocator/TRoServerLocatorCollection in TRoChannel.
I studied the FailOver sample but all the TRoServerLocation objects are already created at design time there.
The problem I have is that the Create function of TRoServerLocator is requiring a Collection that I don’t know where to find. Is it the TRoServerLocationCollection property of TRoChannel? Could you send me an example of how to create it at runtime?
FCanal := TROIndyHTTPChannel.Create(nil);
FCanal.DispatchOptions := FCanal.DispatchOptions + [doFaultTolerant];
FCanal.ProbeServers := true;
//
// TServerInfo = record
// Ip: string;
// Porta: integer;
// Nome: string
// end;
for serverInfo in servidorInfoColection do begin
locator := FCanal.ServerLocators.Add;
with locator do begin
DisableOnFailure := true;
Enabled := true;
Host := serverInfo.Ip;
Port := serverInfo.Porta;
ProbingOptions := ProbingOptions + [poProbeWhenEnabled];
ProbingOptions := ProbingOptions + [poProbeWhenDisabled];
ProbingOptions := ProbingOptions + [poEnableIfProbeSucceeded];
ProbingOptions := ProbingOptions + [poDisableIfProbeFailed];
Name := serverInfo.Nome;
LoadBalancingServer := true;
TargetUrl := 'http://' + Host + ':' + IntToStr(Port) + '/' + path + '/';
end;
FCanal.TargetUrl := locator.TargetUrl;
end;
...
I start 2 servers (127.0.0.1:8090 and 127.0.0.1:8091).
I setup client to read IP/Port from an INI and create a list which I read and create each TROServerLocator above. The Problem:
The client always connects in the last server and if I shutdown the last server, it cannot go to the first server as in the sample.
I don’t know which other properties I should have to change in order to have it automatically connects to the first available server in the list.
Yes, At first (in the code above), I’ve just set channel.DispatchOptions := [doFaultTolerant]; but changed now to
channel.DispatchOptions := [doFaultTolerant, doLoadBalanced]; with the same result.
I’ve created one.
Based on the LoadBalance sample.
First, as I used originally HTTPServer, I changed the server and client to HTTP. With the same components as the original sample but Http. It worked.
Then, I started creating the components in code (at runtime). Created TRoIndyHttpChannel, TRoBinMessage, TRoRemoteService, hooked them all and it worked.
Then, I created TRoDynamicRequest and it doesn’t work
The problem is with the method: RefreshParameters. It seems to require a working server in order to work. As the server is disabled, it should try to go to next server and execute RefreshParameters on it (as it would if you don’t have TRoDynamicRequest and executes server method directly from the interface) but it doesn’t do that and all the remaining code doesn’t get executed.
Attached are the projects (client and server).LoadBalancing.zip (64.5 KB)
see implementation of procedure TRODynamicRequest.RefreshParams(aPersistValues: boolean); but instead of RemoteService.GetRODLLibrary(); use your local TRODLLibrary where .RODL was loaded
OK, before I do that, I simplified my application and are using hard coded interfaces (not using TRoDynamicRequest) in order to avoid the refreshParams problem and the FaultTolerant option is working now: if I don’t have an active server, it tries to execute code in the next server, etc.
But, I designed the server to accept two TRoBinMessages (one for the server’s working interface and the other for controlling the working interface).
So, to shutdown the interface (in order to do some maintenance, etc), I disable the working interface using the code below:
procedure TsrvControl.DisableWorkingInterface;
var
nomeDispatcher: string;
begin
nomeDispatcher := 'ROMessage';
ROServer.Dispatchers.DispatcherByName(nomeDispatcher).Enabled := false;
end;
When I do that (enabling and disabling the working interface this way), the fail-over doesn’t work, eg, it should see that the first server interface is disabled and try the next server but it throws and error: Invalid binary header Either incompatible or not a binary message
(you could simulate that using the load balancing sample).
I could simplify my server using two TRoServer components (one for working operations and the other to control the first server) but this would require one aditional open port at server station.
the fail-over feature will work when server isn’t accessible.
in your case, server is accessible but isn’t properly configured, i.e. dispatcher is disabled
I can suggest to handle admin and usual services on different ports, in this case you can stop usual service and restart it after maintenance
OK, I will go that way. Just to make it clear, when you say “handle admin and usual services on different ports”, you are saying to drop two TRoServers in the main unit and configure it accordingly, it is correct?
yes. you even can drop two different components like tcp server for admin purposes and http server for usual access.
Note: each server should use personal message components