Tuesday, March 11, 2008

client/server architecture for COODBMS

OK, we now have optional .cfg files for configuring databases, and even provision for defaultDatabase.cfg when there is no .cfg file specific to a new database. Common is now part of the CowDb jar file. DRM is now part of the COODBMS jar file. And I'll start work on the client-side DRM tomorrow morning. Time to speculate about the client/server architecture.

As CowDb already supports an advanced threading model, we need to take care to realize the potential of this threading model in the new architecture. I am also concerned that most databases seem designed to support 2-tier architecture and not 3-tier. I.E. You need to dedicate a client thread for each parallel database access. Not a good thing, especially for fully asynchronous web servers which otherwise manage very well with a single thread, e.g. Python Twisted.

So lets say that we will have one (or more) socketts for each client, but each sockett is fully asynchronous and bi-directional. A client then can pump a series of requests for different users through a single socket and process the responses as they arrive. OK, then each request needs to be tagged and the response needs to carry that same tag. However, we will not make any promises about the order in which the responses are returned. Simple clients then can treat the socketts as if they were synchronous, waiting for a response before sending the next request. Clients serving multiple users should generally wait for a response before sending another request from the same user, but that is strictly a client issue.

Implementing this should not be too difficult. We dedicate two threads per sockett--one for reading and another for writing. There can be a single ArrayBlockingQueue per open database to which all the sockett reader threads will put the requests they have received for each database. For each sockett there will be a ConcurrentLinkedQueue which will provide the responses for the sockett writer threads. Further, requests placed in the ArrayBlockingQueues must carry a reference to the ConcurrentLinkedQueue to which the response is to be returned. Executors.newFixedThreadPools can then be used to service the requests read from the ArrayBlockingQueues, with the number of threads allocated for servicing a database being configurable for each database.

We can create the ArrayBlockingQueues and thread pools dynamically as requests for previously unopened databases are received. Conversly, as databases become idle we can free up these resources as well.

The expectation here is that the number of clients will be small, trusted, local to the database server, and long-running. I.E. We are targeting a 3-tier system rather than 2-tier.

One of the considerations that this design addresses is that a given database can only service one update request at a time. So we don't want too many threads ending up servicing the same popular database and consequently blocking access to other, less popular databases. One design issue then is the action to be taken when an ArrayBlockingQueue handling the service requests for a particular database becomes full. If the sockett reader thread waits for space in the queue, then the client can not submit requests on that socket for other databases. But we do not want to dedicate a sockett per database per client.

One answer is to make the ArrayBlockingQueue moderately large and to have clients manage the number of outstanding requests for any given database. Having flow control at the source helps avoid congestion, so long as the number of outstanding requests allowed is large enough to maximize throughput.

Another thing we can do is to have a seperate ArrayBlockingQueue and thread pool for each database X client. Now these resources can be freed when there have not been any requests for a given database from a given client for some time. And a database would be closed only when all of its ArrayBlockingQueues have been closed. And with different sets of ArrayBlockingQueues for each client, only the misbehaving client will suffer congestion problems. Of course, a client can choose to have multiple sockett connections to the database server as well.

0 Comments:

Post a Comment

<< Home