From c7c0828a076896ff9bc66e14cd12337610f69260 Mon Sep 17 00:00:00 2001 From: JackH408 <141727294+JackH408@users.noreply.github.com> Date: Sun, 17 Mar 2024 18:45:13 +1100 Subject: [PATCH] docs: Finished Explanation for Leader/Followers #2239 (#2733) * Added documentation for Feature Toggle design pattern * Explanation for Feature Toggle Issue #2230 finished, added intent, explanation, programmatic example, applicability and consequences * Finished Explanation for Leader/Followers #2239 --- leader-followers/README.md | 93 ++++++++++++++++++++++++++++++++++---- 1 file changed, 84 insertions(+), 9 deletions(-) diff --git a/leader-followers/README.md b/leader-followers/README.md index 6c24e33bf..519809788 100644 --- a/leader-followers/README.md +++ b/leader-followers/README.md @@ -3,28 +3,103 @@ title: Leader/Followers category: Concurrency language: en tag: - - Performance +- Performance --- ## Intent -The Leader/Followers pattern provides a concurrency model where multiple -threads can efficiently de-multiplex events and dispatch event handlers -that process I/O handles shared by the threads. +The Leader/Followers design pattern is a pattern used to coordinate a selection of 'workers'. It allows tasks to execute concurrently +with the Leader delegating tasks to the Follower threads for execution. It is a very common design pattern used in multithreaded +situations such as servers, and works to help prevent ambiguity around delegation of tasks. +## Explanation +Real-world Example +> The best real world example of Leader/Followers is a web server. Web servers have to be able to handle a multitude of incoming +> connections all at once. In a web server, the Leader/Followers pattern works by using the Leader to listen to incoming requests +> and accept connections. Once a connection is made to a client the Leader can then find a Follower thread to delegate the task +> to for execution and return to the client. This means that the Leader does not have to wait to finish execution before it can +> accept another incoming connection, and can focus on delegating tasks. This pattern is created to aid in concurrency of applicaitons, +> allowing for many connections to work simultaneously. + +In plain words +> You can picture the Leader as a traffic controller that has to direct traffic from one lane into 25 lanes. As a car comes in, +> the Leader sends it down a road that isn't full or busy. This car can then have its request filled, or reach its destination. +> If the Leader had to drive each car down the lane itself, the line would pile up and progress would be slow. But as the Leader +> has Followers that can also drive the cars, the Leader can focus on making the line move quickly and ensuring traffic doesn't +> back up. + +Wikipedia says +> A concurrency pattern are those types of design patterns that deal with the multi-threaded programming paradigm. + +## Programmatic Example +This example shows Java code that sets up a Leader that listens for client requests on port 8080. Once a request is sent, +the leader will accept it and delegate it to a new Follower to execute. This means that the Leader can keep delegating, +and ensure requests are fulfilled timely. This is only pseudocode and the working code would require a more concrete implementation +of Leader and Followers. +```java +public class LeaderFollowerWebServer { + + public static void main(String[] args) throws IOException { + int port = 8080; // the port that clients can reach the leader on + int numFollowers = 5; // the amount of followers we can delegate tasks to + + ServerSocket serverSocket = new ServerSocket(port); // pseudocode for creating a socket to the server + ExecutorService executorService = Executors.newFixedThreadPool(numFollowers); // pseudocode to start execution for Followers + + System.out.println("Web server started. Listening on port " + port); + + while (true) { + Socket clientSocket = serverSocket.accept(); + // Accept a new connection and assign it to a follower thread for processing + executorService.execute(new Follower(clientSocket)); + } + } +} + +class Follower implements Runnable { + private final Socket clientSocket; + + public Follower(Socket clientSocket) { + this.clientSocket = clientSocket; + } + + @Override + public void run() { + try { + // handle the client request, e.g., read and write data + // this is where you would implement your request processing logic. + // we will just close the socket + clientSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} +``` ## Class diagram ![Leader/Followers class diagram](./etc/leader-followers.png) ## Applicability Use Leader-Followers pattern when -* multiple threads take turns sharing a set of event sources in order to detect, de-multiplex, dispatch and process service requests that occur on the event sources. +* You want to establish a concurrent application +* You want faster response times on heavy load +* You want an easily scalable program +* You want to load balance a program + +## Consequences +Consequences involved with using the Leader/Followers pattern + +* Implementing this pattern will increase complexity of the code +* If the leader is too slow at delegating processes, some Followers may not get to execute tasks leading to a waste of resources +* There is overhead with organising and maintaining a thread pool +* Debugging is more complex ## Real world examples -* [ACE Thread Pool Reactor framework](https://www.dre.vanderbilt.edu/~schmidt/PDF/HPL.pdf) -* [JAWS](http://www.dre.vanderbilt.edu/~schmidt/PDF/PDCP.pdf) -* [Real-time CORBA](http://www.dre.vanderbilt.edu/~schmidt/PDF/RTS.pdf) +* ACE Thread Pool Reactor framework +* JAWS +* Real-time CORBA ## Credits -* [Douglas C. Schmidt and Carlos O’Ryan - Leader/Followers](http://www.kircher-schwanninger.de/michael/publications/lf.pdf) +* Douglas C. Schmidt and Carlos O’Ryan - Leader/Followers \ No newline at end of file