|
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