public static void main(String[] args) throws InterruptedException { final TradeServer server = new TradeServer(); // Use a Reactor to dispatch events using the default Dispatcher Reactor reactor = new Reactor(); // Create a single Selector for efficiency Selector trade = $("trade.execute"); // For each Trade event, execute that on the server reactor.on( trade, new Consumer<Event<Trade>>() { @Override public void accept(Event<Trade> tradeEvent) { server.execute(tradeEvent.getData()); // Since we're async, for this test, use a latch to tell when we're done latch.countDown(); } }); // Start a throughput timer startTimer(); // Publish one event per trade for (int i = 0; i < totalTrades; i++) { // Pull next randomly-generated Trade from server Trade t = server.nextTrade(); // Notify the Reactor the event is ready to be handled reactor.notify(trade, Fn.event(t)); } // Stop throughput timer and output metrics endTimer(); server.stop(); }
public static void main(String[] args) throws Exception { Environment env = new Environment(); final TradeServer server = new TradeServer(); // Use a Reactor to dispatch events using the high-speed Dispatcher final Reactor serverReactor = Reactors.reactor(env); // Create a single key and Selector for efficiency final Selector tradeExecute = Selectors.object("trade.execute"); // For each Trade event, execute that on the server and notify connected clients // because each client that connects links to the serverReactor serverReactor.on( tradeExecute, (Event<Trade> ev) -> { server.execute(ev.getData()); // Since we're async, for this test, use a latch to tell when we're done latch.countDown(); }); @SuppressWarnings("serial") WebSocketServlet wss = new WebSocketServlet() { @Override public void configure(WebSocketServletFactory factory) { factory.setCreator( (req, resp) -> new WebSocketListener() { AtomicLong counter = new AtomicLong(); @Override public void onWebSocketBinary(byte[] payload, int offset, int len) {} @Override public void onWebSocketClose(int statusCode, String reason) {} @Override public void onWebSocketConnect(final Session session) { LOG.info("Connected a websocket client: {}", session); // Keep track of a rolling average final AtomicReference<Float> avg = new AtomicReference<>(0f); serverReactor.on( tradeExecute, (Event<Trade> ev) -> { Trade t = ev.getData(); avg.set((avg.get() + t.getPrice()) / 2); // Send a message every 1000th trade. // Otherwise, we completely overwhelm the browser and network. if (counter.incrementAndGet() % 1000 == 0) { try { session .getRemote() .sendString(String.format("avg: %s", avg.get())); } catch (IOException e) { if (!"Failed to write bytes".equals(e.getMessage())) { e.printStackTrace(); } } } }); } @Override public void onWebSocketError(Throwable cause) {} @Override public void onWebSocketText(String message) {} }); } }; serve(wss); LOG.info( "Connect websocket clients now (waiting for 10 seconds).\n" + "Open websocket/src/main/webapp/ws.html in a browser..."); Thread.sleep(10000); // Start a throughput timer startTimer(); // Publish one event per trade for (int i = 0; i < totalTrades; i++) { // Pull next randomly-generated Trade from server Trade t = server.nextTrade(); // Notify the Reactor the event is ready to be handled serverReactor.notify(tradeExecute.getObject(), Event.wrap(t)); } // Stop throughput timer and output metrics endTimer(); server.stop(); }