How to handle multiple service hosts in XData

I've been doing dev work with a service derived from the Swagger demo. It's working fine running on localhost.

Now I want to migrate my service to a remote server, and I can't see how to configure it with the options given in the XData.Service interface.

I'd actually like to have multiple services running, with one being localhost (for testing), and the others being remote, and selected on the client by some means based on, say, where the user is located in the world. Perhaps when my app starts, it runs tests on all servers to see which one gets the best round-trip response time, and select that one. I could run that test periodically and always select the fastest one.

So how would I set up an array (on the client) of XData services running both as localhost and on multiple remote hosts? (The localhost version wouldn't be distributed to my customers; it's just for my own testing.) Is this documented somewhere?

I don't recall running across this in the documentation anywhere, but maybe one of the TMS people will be able to better clarify that.

I have a similar situation and I can offer up some ideas for you to consider though. All of this is in the client, assuming that the client knows where your XData servers are, or can reach at least one of them and retrieve the rest via one of the services.

It sounds like you'll want to define a "global" XData connection once, perhaps in a WebDataModule, for example. And then establish that connection when your first app starts and use that connection everywhere in your application afterwards. Kind of obvious I guess, but just being clear here.

For the dev/localhost scenario, it may be an idea to pass a parameter to your client application that can be used to determine whether to configure that global connection to point at localhost. So when that WebDataModule is first created, check and see if the parameter is set. This would allow you to set the parameter in the Delphi IDE for example (assuming a TMS Web Core or other Delphi-basied client here) and then work away without having to think about it too much while you're doing the development and testing of the app. And then in the production environment (or when testing other XData servers) just take away the parameter.

For the situation of having multiple remote clients, yes, creating a connection to each server and timing how long it takes to establish a connection and then selecting the best one is an option, though it might end up being a lot of traffic and a bit of a delay at app start up depending on how many servers you're going to be testing. It may be an idea to write to LocalStorage the value of the server you determine as best so that you don't have to check them all each time the app starts.

You can probably do something pretty simple just using an array of Integer values and an array of URL's that point to the XData Servers and simply perform the connections in a loop with await, setting the array of Integers using MillisecondsBetween to calculate the time between connections. And then just look at the array to see which has the lowest value. Something like that?

Lots of options here depending on how many XData servers, how much time is acceptable to wait in determining the best server to connect to, how much traffic is expected from just this determination, and so on. I'm sure there are others ready to offer additional insight depending on your particular scenario!

1 Like

Another reason you'd want this kind of mechanism might be to have some degree of fault tolerance. If one of the XData servers is down for example (due to an update or a host being rebooted or something) then the app could automatically select an alternate XData server to connect to.

1 Like

Thanks, Andrew, but none of this is what's puzzling me.

Let's say I have an instance of my service running at localhost, and four others on servers located on different continents.

How the heck do I parameterize these and know which one is which?

*** Ahh, I think I figured it out ***

I'm guessing I need separate XDataClient instances (?)

I was looking for a way to parameterize it on the .Service method.

  MyService : array of IMyService;
  . . .
  XDataClient_local := TXDataClient.Create;
  XDataClient_local.Uri := 'http://localhost:2001/abc/my_service';
  XDataClient2 := TXDataClient.Create;
  XDataClient2.Uri := 'http://1.2.3.4:1111/';
  XDataClient3 := TXDataClient.Create;
  XDataClient3.Uri := 'http://10.20.30.40:2222/';
  XDataClient4 := TXDataClient.Create;
  XDataClient4.Uri := 'http://100.110.120.130:3333/';
  XDataClient5 := TXDataClient.Create;
  XDataClient5.Uri := 'http://192.168.100.37:4444/';

  SetLength( MyService, 5 );
  MyService[0] := XDataClient_local.Service<IMyService>;  // localhost = 192.168.0.?:????
  MyService[1] := XDataClient2.Service<IMyService>;  // 1.2.3.4:1111
  MyService[2] := XDataClient3.Service<IMyService>;  // 10.20.30.40:2222
  MyService[3] := XDataClient4.Service<IMyService>;  // 100.110.120.130:3333
  MyService[4] := XDataClient5.Service<IMyService>;  // 192.168.100.37:4444

Something else comes to mind as I'm looking at that: how do we support https connections?

Sort of. I guess there are different ways of connecting to an XData server. I use TXDataWebConnection for example, and it's URL property which can specify HTTPS. Same sort of idea though.

And just create a loop where you change the URL and test the connection time. Pick the connection with the lowest time and use that for the connection. Maybe cache the result so you don't have to check again for some period of time.

If you wanted to be fancy, the URL list could be a "seed list" and the timing test could actually be just the time taken to download the full list of URLs from a server endpoint that provides a full list. Like if you had dozens that change regularly. So you don't have to publish them all in the app.

As far as HTTPS, there IS information in the docs about that. Works pretty well I think, not sure I'd want to add anything there. I use it, it works, I don't think I've ever had to think much about it. Not necessarily all that intuitive but if you have any questions after reviewing the docs I'm sure there are lots of folks here who would be more than happy to help.

1 Like

Thanks Andrew, but you are misunderstanding my question. I'm pretty sure I figured it out.

I'll look around for info on https.

To access different XData server in different URL addresses, yes, you need one TXDataClient (or TXDataWebConnection) for each of them. Just use one for each XData server you want to connect to.

@AndrewSimard is talking about Web Core client applications (TXDataWebConnection, TXDataWebClient), @Schwartz_David is talking about regular desktop/mobile applications (TXDataClient). Different components, but the idea is the same.

HTTPS usage in client is completely transparent. In the server, you have some explanation here in the documentation: Http Server | TMS Sparkle documentation.