RTC Forums
April 20, 2024, 05:04:44 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Login Register  
Pages: [1]
  Print  
Author Topic: Advice on service architecture  (Read 3745 times)
treebyte_srl
RTC License
***
Posts: 11


« on: October 16, 2014, 01:57:25 PM »

Hello,

I need some general advices on a project architecture (Delphi XE5).

My purpose is to develop a Windows service that returns various type of data coming from an Oracle database and that respond to a client application.

Server side, actually, I have the following components put inside a TService:

1) a TrtcHttpServer + TrtcServerModule. TrtcHttpServer have MultiThreaded := True and Blocking := False
2) a number of TrtcFunctions components that performs the requests to database and returns data to the client ?
3) one Session (database) component, create at design time, that will be connected to DB on OnServiceStart event
4) a number of TQuery and TStoredProc components, created ad design time, that phisically performs queries on database.

For database connectivity, I use SQLDirect (but this shouldn't be a critical point).

Client side, I have a VCL applications (32 bit) that performs requests on http server. Clients can be both on the same LAN, but also and expecially on different locations connected through ADSL and VPN.
Client program uses a TrtcHttpClient + TrtcClientModule component, plus a TrtcResult component for every kind of request. Client requests are non-blocking (using Call method) for query requests, and blocking using (Execute method) for stored-procedure requests.

Whit this architecture, the service and client works. Sometimes, the server don't answer to a request, so the client seems to be hang.

So, my questions are two:

Server side: what I developer until now, is the best approach ? Or there are some better solutions I can implement (e.g. using a DB connection pool, create database and queries components at runtime inside every TrtcFunctionsExecute event) ?

Client side: what is the best event to understand if a request failed ? I actually use TrtcResult.OnRequestAborted, that works fine for networking problems or if the service is stopped, but not when the service will not answer. Basically, I would like to understand how to implement a timeout management. Help is not very clear on this point, IMO (or I don't search well  Embarrassed ).

Thanks in advice. If something is not clear, feel free to ask everything (english is not my 1st language).

Giuseppe Garzotto
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #1 on: October 16, 2014, 03:02:20 PM »

Server side:

If your Server is Multi-Threaded and you are using a single Database Session component, you will need to use critical sections to secure access to the Database components, which effectively makes all your Database access code single-threaded, because only one thread is allowed to use a single set of Database access components at a time. If you want your Server to have the abbility to execute more than one remote function call with Database access at the same time (multi-threaded), you either need to create and destroy Database components on-demand inside your remote functions, or implement a Database connection pool to reuse Database connections and thus avoid having to open and close a Database connection for every single Database-related request.

Client side:

A) When using the TRtcClientModule component in event-driven mode (Call method), if a remote call could not be completed due to connection problems, the OnResponseAbort event will be triggered on the TRtcClientModule component and the RequestAborted event will be triggered on the TRtcResult component used as a parameter for the Call.

B) When using the TRtcClientModule component in blocking mode (Execute method), there will be an exception raised if the call failed for any reason. You can use a timeout value in the Execute method to define how long you are willing to wait for the result. This timeout value should include the time required to send the request to the Server, Execute the remote function on the Server and receive a result from the Server. If you decide to use timeout values, make sure to give the Server enough time to handle your request and any other eventually pending requests on the Server, so you don't start experiencing timout exceptions when the Server slows down due to heavy load.

Best Regards,
Danijel Tkalcec
Logged
treebyte_srl
RTC License
***
Posts: 11


« Reply #2 on: October 16, 2014, 03:40:46 PM »

Hello Danijel,

Many thanks for the clear and quick answer.

Client side, everything is clear.

Server side, I have a doubt: when you say
Quote
you either need to create and destroy Database components on-demand inside your remote functions
(that is the approach I'm trying to use), do you mean create and destroy only the database / session component, or also the query and stored procedure components involved in the request ?

Again, thanks for your valuable support.

Giuseppe Garzotto
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #3 on: October 16, 2014, 05:30:48 PM »

You need a complete unique set of all components required for Database access (Session, Database, Query, Table, ...) for each thread. You can not use the same Database or Session or Query or Table component from more than one thread at a time. You can either create all the components in code which are needed for Database access, or you can put on a Data Module at design-time, then create a separate instance of that Data Module when you need a new set of Database access components. You can also implement a pool of such Data Module instances, to function as your Database Connection Pool. There are already topics in this Forum about imlementing database connection pools. You can find them by using the Forum Search feature (right top corner).

Best Regards,
Danijel Tkalcec
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.025 seconds with 16 queries.