Reactive Cloud-Native Networking info@netifi.com www.netifi.com
Speakers • Arsalan Farooq CEO • Robert Roeser CINO • Founder/CEO of Convirture • Netflix Edge Platform team (acquired by Accelerite) • RSocket core contributor • Founded Oracle’s ASLM • Principal Architect at Nike division and grew it to a on realtime analytics multi-national organization system serving 30M+ users
• Open Source Layer 5/6 communication protocol • Reactive streams semantics • Application-level flow control • Binary Encoding Built by leaders in microservices • Asynchronous Message-Passing and cloud computing
What’s needed for high performance Microservice Networking?
High Performance Microservices • Temporal Decoupling • Spacial Decoupling • Binary • Application-Flow control � 5
Loose Coupling Spacial Decoupling Temporal Decoupling A message’s sender should not The execution time processing a directly call a destination call should not affect the caller
RSocket is loosely coupled using message-passing.
What’s the difference between Message-Passing and Event-Driven?
Message-Passing vs Event-Driven Message-Passing Event-Driven An event is signal emitted by a component reaching A message is a payload sent to a specific destination a specific stage Message-driven focuses on addressable recipients Event drive focuses on listen for events Errors passed as messages - can be easy sent to Error handling in Event driven very complex - think caller dead letter queues Bi-directional communication is very hard in Event- Bi-directional communication is easy driven � 9
Event-Driven Queue Emits Events Listens for Events � 10
Event-Driven Queue Emits Events Listens for Events � 11
Event-Driven Queue Emits Events Listens for Events � 12
Event-Driven Queue Emits Events Listens for Events � 13
Event-Driven Queue Emits Events Listens for Events � 14
Event-Driven Queue ??? response Emits Events Listens for Events � 15
Event-Driven Queue ??? exception Emits Events Listens for Events � 16
Event-Driven Queue ??? backpressure Emits Events Listens for Events � 17
Message-Passing Dest 1 Dest 4 Dest 2 Dest 5 Dest 3 Dest 6 � 18
Message-Passing Dest 1 Dest 4 Dest 2 Dest 5 Dest 3 Dest 6 � 19
Message-Passing Dest 1 Dest 4 Dest 2 Dest 5 Dest 3 Dest 6 � 20
Message-Passing Dest 1 Dest 4 Dest 2 Dest 5 Dest 3 Dest 6 � 21
RSocket - Message-Passing Dest 1 Dest 2 � 22
RSocket - Message-Passing requestChannel Dest 1 Dest 2 � 23
RSocket - Message-Passing requestChannel Dest 1 Dest 2 request(3) � 24
RSocket - Message-Passing Payload requestChannel Dest 1 Dest 2 request(3) � 25
RSocket - Message-Passing Payload Payload requestChannel Dest 1 Dest 2 request(3) � 26
RSocket - Message-Passing Payload Payload Payload requestChannel Dest 1 Dest 2 request(3) � 27
RSocket - Message-Passing Payload Payload request(2) Payload requestChannel Dest 1 Dest 2 request(3) � 28
RSocket - Message-Passing Payload Payload request(2) Payload requestChannel Dest 1 Dest 2 complete request(3) � 29
RSocket - Message-Passing Payload Payload request(2) Payload requestChannel Dest 1 Dest 2 request(3) � 30
RSocket - Message-Passing Payload Payload request(2) Payload requestChannel Dest 1 Dest 2 exception request(3) � 31
RSocket - Loose Coupling Spacial Decoupling Temporal Decoupling RSocket messages are binary RSocket’s APIs are non-blocking frames over dedicated streams
What type of Messages does RSocket use?
RSocket’s Messages Binary Payloads Flyweight Pattern Efficiently encoded binary Resumable lens over bytes to payloads access messages
How does RSocket Process Messages?
It’s easy to get processing wrong.
Key Insight public class Counter1 { private int count; private int count() { //count = 0; for (int i = 0; i < Integer. MAX_VALUE ; i++) { count++; } return count; } public static void main(String... args) { final Counter1 counter1 = new Counter1(); final Recorder histogram = new Recorder(3600000000000L, 3); for (int i = 0; i < 100; i++) { long start = System. nanoTime (); counter1.count(); long stop = System. nanoTime (); histogram.recordValue(stop - start); } histogram .getIntervalHistogram() .outputPercentileDistribution(System. out , 5, 1000.0, false); } }
Key Insight public class Counter1 { private int count; private int count() { //count = 0; for (int i = 0; i < Integer. MAX_VALUE ; i++) { count++; } return count; } public static void main(String... args) { final Counter1 counter1 = new Counter1(); Single final Recorder histogram = new Recorder(3600000000000L, 3); Count Counter Main for (int i = 0; i < 100; i++) { long start = System. nanoTime (); counter1.count(); long stop = System. nanoTime (); histogram.recordValue(stop - start); } histogram .getIntervalHistogram() .outputPercentileDistribution(System. out , 5, 1000.0, false); } }
Key Insight public class Counter1 { private int count; private int count() { //count = 0; for (int i = 0; i < Integer. MAX_VALUE ; i++) { count++; } return count; } public static void main(String... args) { final Counter1 counter1 = new Counter1(); Single final Recorder histogram = new Recorder(3600000000000L, 3); Count Counter Main for (int i = 0; i < 100; i++) { long start = System. nanoTime (); counter1.count(); long stop = System. nanoTime (); histogram.recordValue(stop - start); } histogram .getIntervalHistogram() .outputPercentileDistribution(System. out , 5, 1000.0, false); } } Takes about 1 microsecond.
Key Insight public class Counter2 { private static AtomicIntegerFieldUpdater<Counter2> COUNT = AtomicIntegerFieldUpdater. newUpdater (Counter2.class, "count"); private volatile int count; private int count() throws Exception { int target = Integer. MAX_VALUE ; count = 0; ExecutorService executor = Executors. newCachedThreadPool (); for (int i = 0; i < Runtime. getRuntime ().availableProcessors(); i++) { executor.execute(() -> { while ( COUNT .incrementAndGet(Counter2.this) < target) Thread. yield (); }); } while ( COUNT .get(Counter2.this) < target) Thread. yield (); return count; } public static void main(String... args) throws Exception { final Counter2 counter = new Counter2(); final Recorder histogram = new Recorder(3600000000000L, 3); for (int i = 0; i < 100; i++) { long start = System. nanoTime (); counter.count(); long stop = System. nanoTime (); histogram.recordValue(stop - start); } histogram.getIntervalHistogram().outputPercentileDistribution(System. out , 5, 1000.0, false); } }
Key Insight public class Counter2 { private static AtomicIntegerFieldUpdater<Counter2> COUNT = AtomicIntegerFieldUpdater. newUpdater (Counter2.class, "count"); private volatile int count; private int count() throws Exception { int target = Integer. MAX_VALUE ; count = 0; ExecutorService executor = Executors. newCachedThreadPool (); for (int i = 0; i < Runtime. getRuntime ().availableProcessors(); i++) { executor.execute(() -> { while ( COUNT .incrementAndGet(Counter2.this) < target) Thread. yield (); }); } Multi-threaded while ( COUNT .get(Counter2.this) < target) Thread. yield (); Counter return count; } Counter Main Count public static void main(String... args) throws Exception { final Counter2 counter = new Counter2(); final Recorder histogram = new Recorder(3600000000000L, 3); Counter for (int i = 0; i < 100; i++) { long start = System. nanoTime (); counter1.count(); long stop = System. nanoTime (); histogram.recordValue(stop - start); } histogram.getIntervalHistogram().outputPercentileDistribution(System. out , 5, 1000.0, false); } }
Key Insight public class Counter2 { private static AtomicIntegerFieldUpdater<Counter2> COUNT = AtomicIntegerFieldUpdater. newUpdater (Counter2.class, "count"); private volatile int count; private int count() throws Exception { int target = Integer. MAX_VALUE ; count = 0; ExecutorService executor = Executors. newCachedThreadPool (); for (int i = 0; i < Runtime. getRuntime ().availableProcessors(); i++) { executor.execute(() -> { while ( COUNT .incrementAndGet(Counter2.this) < target) Thread. yield (); }); } Multi-threaded while ( COUNT .get(Counter2.this) < target) Thread. yield (); Counter return count; } Counter Main Count public static void main(String... args) throws Exception { final Counter2 counter = new Counter2(); final Recorder histogram = new Recorder(3600000000000L, 3); Counter for (int i = 0; i < 100; i++) { long start = System. nanoTime (); counter1.count(); long stop = System. nanoTime (); histogram.recordValue(stop - start); } histogram.getIntervalHistogram().outputPercentileDistribution(System. out , 5, 1000.0, false); } } Didn’t wait for it to finish.
Recommend
More recommend