-
Notifications
You must be signed in to change notification settings - Fork 19
Client Server Mechanism
The client–server model is a distributed application structure that partitions tasks or workloads between the providers of a resource or service, called servers, and service requesters, called clients. Often clients and servers communicate over a computer network on separate hardware, but both client and server may reside in the same system.
There are 3 type of clients which communicates with the server - Manager, Worker and cart. All the clients are able to communicate simultaneously to send requests and update the supermarket database.
The clients use an object from ClientRequestHandler class to initialize socket which will be used to send requests to the server and receive the responds from it as well. An object from ClientRequestHandler class throws exceptions on failure which the client must deal with (such as connection problems and responds timeout). The client can set timeout for the waiting time for the respond.
The server send/receive communication is a little bit more complicated than the client side. The server waits for clients connections, when the server accepts a request, it processes the request (using SQL server) and sends a respond if needed. So far no so complicated... but here is the catch: The server must deal with a lot of requests from clients as fast as it can. Well, for such mission we must use parallelism. The server needs to be idle to accept new request while processing others. There are 2 common ways to deal with the clients' request:
The server listens to the server socket port. Whenever a request is received, the server will create a thread (worker) which will communicate on a different port and will process the client request. What's the big advantaged over a Single threaded server? Well, this way the thread listening for incoming requests spends as much time as possible in the serverSocket.accept() call. That way the risk is minimized for clients being denied access to the server because the listening thread is not inside the accept() call.
Multithreaded Server Advantages
The advantages of a multithreaded server compared to a single threaded server are summed up below:
Less time is spent outside the accept() call. Long running client requests do not block the whole server As mentioned earlier the more time the thread calling serverSocket.accept() spends inside this method call, the more responsive the server will be. Only when the listening thread is inside the accept() call can clients connect to the server. Otherwise the clients just get an error.
In a single threaded server long running requests may make the server unresponsive for a long period. This is not true for a multithreaded server, unless the long-running request takes up all CPU time time and/or network bandwidth.
The thread pooled server has a pool of threads. The number of threads which are running is fixed (doesn't depend on the server work to accept new requests). The pool is a synchronized Consumer-Producer queue - When a request arrives, an idle thread from the pool will execute the process operation. When the thread finished its process work, it will be returned to the pool.
Thread Pooled Server Advantages
The advantages of a thread pooled server compared to a multithreaded server is that you can control the maximum number of threads running at the same time. This has certain advantages.
First of all if the requests require a lot of CPU time, RAM or network bandwidth, this may slow down the server if many requests are processed at the same time. For instance, if memory consumption causes the server to swap memory in and out of disk, this will result in a serious performance penalty. By controlling the maximum number of threads you can minimize the risk of resource depletion, both due to limiting the memory taken by the processing of the requests, but also due to the limitation and reuse of the threads. Each thread take up a certain amount of memory too, just to represent the thread itself.
Additionally, executing many requests concurrently will slow down all requests processed. For instance, if you process 1.000 requests concurrently and each request takes 1 second, then all requests will take 1.000 seconds to complete. If you instead queue the requests up and process them say 10 at a time, the first 10 requests will complete after 10 seconds, the next 10 will complete after 20 seconds etc. Only the last 10 requests will complete after 1.000 seconds. This gives a better service to the clients.
After we reviewed the server implementation options (of course there are more options), we decided that the Thread Pooled Server will serve our needs the best way. In the future, when the server will have to support hundreds of request from clients, it will be able to answer as fast as possible.