|
10 | 10 | import com.iluwatar.reactor.framework.ThreadPoolDispatcher; |
11 | 11 |
|
12 | 12 | /** |
13 | | - * This application demonstrates Reactor pattern. The example demonstrated is a Distributed Logging Service |
14 | | - * where it listens on multiple TCP or UDP sockets for incoming log requests. |
| 13 | + * This application demonstrates Reactor pattern. The example demonstrated is a Distributed Logging |
| 14 | + * Service where it listens on multiple TCP or UDP sockets for incoming log requests. |
15 | 15 | * |
16 | 16 | * <p> |
17 | | - * <i>INTENT</i> |
18 | | - * <br/> |
19 | | - * The Reactor design pattern handles service requests that are delivered concurrently to an |
| 17 | + * <i>INTENT</i> <br/> |
| 18 | + * The Reactor design pattern handles service requests that are delivered concurrently to an |
20 | 19 | * application by one or more clients. The application can register specific handlers for processing |
21 | 20 | * which are called by reactor on specific events. |
22 | 21 | * |
23 | 22 | * <p> |
24 | | - * <i>PROBLEM</i> |
25 | | - * <br/> |
26 | | - * Server applications in a distributed system must handle multiple clients that send them service |
| 23 | + * <i>PROBLEM</i> <br/> |
| 24 | + * Server applications in a distributed system must handle multiple clients that send them service |
27 | 25 | * requests. Following forces need to be resolved: |
28 | 26 | * <ul> |
29 | 27 | * <li>Availability</li> |
|
33 | 31 | * </ul> |
34 | 32 | * |
35 | 33 | * <p> |
36 | | - * The application utilizes single thread to listen for requests on all ports. It does not create |
37 | | - * a separate thread for each client, which provides better scalability under load (number of clients |
| 34 | + * <i>PARTICIPANTS</i> <br/> |
| 35 | + * <ul> |
| 36 | + * <li>Synchronous Event De-multiplexer</li> {@link NioReactor} plays the role of synchronous event |
| 37 | + * de-multiplexer. It waits for events on multiple channels registered to it in an event loop. |
| 38 | + * |
| 39 | + * <p> |
| 40 | + * <li>Initiation Dispatcher</li> {@link NioReactor} plays this role as the application specific |
| 41 | + * {@link ChannelHandler}s are registered to the reactor. |
| 42 | + * |
| 43 | + * <p> |
| 44 | + * <li>Handle</li> {@link AbstractNioChannel} acts as a handle that is registered to the reactor. |
| 45 | + * When any events occur on a handle, reactor calls the appropriate handler. |
| 46 | + * |
| 47 | + * <p> |
| 48 | + * <li>Event Handler</li> {@link ChannelHandler} acts as an event handler, which is bound to a |
| 49 | + * channel and is called back when any event occurs on any of its associated handles. Application |
| 50 | + * logic resides in event handlers. |
| 51 | + * </ul> |
| 52 | + * |
| 53 | + * <p> |
| 54 | + * The application utilizes single thread to listen for requests on all ports. It does not create a |
| 55 | + * separate thread for each client, which provides better scalability under load (number of clients |
38 | 56 | * increase). |
39 | 57 | * |
40 | 58 | * <p> |
|
45 | 63 | */ |
46 | 64 | public class App { |
47 | 65 |
|
48 | | - private NioReactor reactor; |
| 66 | + private NioReactor reactor; |
| 67 | + |
| 68 | + /** |
| 69 | + * App entry. |
| 70 | + * |
| 71 | + * @throws IOException |
| 72 | + */ |
| 73 | + public static void main(String[] args) throws IOException { |
| 74 | + new App().start(); |
| 75 | + } |
| 76 | + |
| 77 | + /** |
| 78 | + * Starts the NIO reactor. |
| 79 | + * |
| 80 | + * @throws IOException if any channel fails to bind. |
| 81 | + */ |
| 82 | + public void start() throws IOException { |
| 83 | + /* |
| 84 | + * The application can customize its event dispatching mechanism. |
| 85 | + */ |
| 86 | + reactor = new NioReactor(new ThreadPoolDispatcher(2)); |
| 87 | + |
| 88 | + /* |
| 89 | + * This represents application specific business logic that dispatcher will call on appropriate |
| 90 | + * events. These events are read events in our example. |
| 91 | + */ |
| 92 | + LoggingHandler loggingHandler = new LoggingHandler(); |
| 93 | + |
| 94 | + /* |
| 95 | + * Our application binds to multiple channels and uses same logging handler to handle incoming |
| 96 | + * log requests. |
| 97 | + */ |
| 98 | + reactor.registerChannel(tcpChannel(6666, loggingHandler)).registerChannel(tcpChannel(6667, loggingHandler)) |
| 99 | + .registerChannel(udpChannel(6668, loggingHandler)).start(); |
| 100 | + } |
| 101 | + |
| 102 | + /** |
| 103 | + * Stops the NIO reactor. This is a blocking call. |
| 104 | + * |
| 105 | + * @throws InterruptedException if interrupted while stopping the reactor. |
| 106 | + */ |
| 107 | + public void stop() throws InterruptedException { |
| 108 | + reactor.stop(); |
| 109 | + } |
49 | 110 |
|
50 | | - /** |
51 | | - * App entry. |
52 | | - * @throws IOException |
53 | | - */ |
54 | | - public static void main(String[] args) throws IOException { |
55 | | - new App().start(); |
56 | | - } |
57 | | - |
58 | | - /** |
59 | | - * Starts the NIO reactor. |
60 | | - * @throws IOException if any channel fails to bind. |
61 | | - */ |
62 | | - public void start() throws IOException { |
63 | | - /* |
64 | | - * The application can customize its event dispatching mechanism. |
65 | | - */ |
66 | | - reactor = new NioReactor(new ThreadPoolDispatcher(2)); |
67 | | - |
68 | | - /* |
69 | | - * This represents application specific business logic that dispatcher will call |
70 | | - * on appropriate events. These events are read events in our example. |
71 | | - */ |
72 | | - LoggingHandler loggingHandler = new LoggingHandler(); |
73 | | - |
74 | | - /* |
75 | | - * Our application binds to multiple channels and uses same logging handler to handle |
76 | | - * incoming log requests. |
77 | | - */ |
78 | | - reactor |
79 | | - .registerChannel(tcpChannel(6666, loggingHandler)) |
80 | | - .registerChannel(tcpChannel(6667, loggingHandler)) |
81 | | - .registerChannel(udpChannel(6668, loggingHandler)) |
82 | | - .start(); |
83 | | - } |
84 | | - |
85 | | - /** |
86 | | - * Stops the NIO reactor. This is a blocking call. |
87 | | - */ |
88 | | - public void stop() { |
89 | | - reactor.stop(); |
90 | | - } |
| 111 | + private static AbstractNioChannel tcpChannel(int port, ChannelHandler handler) throws IOException { |
| 112 | + NioServerSocketChannel channel = new NioServerSocketChannel(port, handler); |
| 113 | + channel.bind(); |
| 114 | + return channel; |
| 115 | + } |
91 | 116 |
|
92 | | - private static AbstractNioChannel tcpChannel(int port, ChannelHandler handler) throws IOException { |
93 | | - NioServerSocketChannel channel = new NioServerSocketChannel(port, handler); |
94 | | - channel.bind(); |
95 | | - return channel; |
96 | | - } |
97 | | - |
98 | | - private static AbstractNioChannel udpChannel(int port, ChannelHandler handler) throws IOException { |
99 | | - NioDatagramChannel channel = new NioDatagramChannel(port, handler); |
100 | | - channel.bind(); |
101 | | - return channel; |
102 | | - } |
| 117 | + private static AbstractNioChannel udpChannel(int port, ChannelHandler handler) throws IOException { |
| 118 | + NioDatagramChannel channel = new NioDatagramChannel(port, handler); |
| 119 | + channel.bind(); |
| 120 | + return channel; |
| 121 | + } |
103 | 122 | } |
0 commit comments