SlideShare a Scribd company logo
1 of 118
Download to read offline
Season 2 Episode 2
July 9, 2014
Evening Outline
Lightning Talks:
● Reactive / Rx
● RxJava
● RxNetty
● Ribbon 2.0
● Karyon 2.0
Guest Speakers
● Jake Wharton, Square
● Matt Ingenthron, Couchbase
● Will Sargent, Typesafe
Netflix Lightning talks
Composable Functions
Reactively Applied
Composable Functions
Reactively Applied
Composable Functions
Reactively Applied
Clojure Scala
Groovy JRuby
Java 8
(->
(Observable/from ["one" "two" "three"])
(.take 2)
(.subscribe (rx/action [arg] (println arg))))
Observable("one", "two", "three")
.take(2)
.subscribe((arg: String) => {
println(arg)
})
Observable.from("one", "two", "three")
.take(2)
.subscribe(lambda { |arg| puts arg })
Observable.from("one", "two", "three")
.take(2)
.subscribe({arg -> println(arg)})
Observable.from("one", "two", "three")
.take(2)
.subscribe(System.out::println);
return new UserCommand(userId).observe().flatMap(user -> {
Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe()
.flatMap(catalogList -> {
return catalogList.videos().<Map<String, Object>> flatMap(video -> {
Observable<Bookmark> bookmark = new BookmarkCommand(video).observe();
Observable<Rating> rating = new RatingsCommand(video).observe();
Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe();
return Observable.zip(bookmark, rating, metadata, (b, r, m) -> {
return combineVideoData(video, b, r, m);
});
});
});
Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> {
return s.getDataAsMap();
});
return Observable.merge(catalog, social);
}).flatMap(data -> {
return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER);
});
return new UserCommand(userId).observe().flatMap(user -> {
Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe()
.flatMap(catalogList -> {
return catalogList.videos().<Map<String, Object>> flatMap(video -> {
Observable<Bookmark> bookmark = new BookmarkCommand(video).observe();
Observable<Rating> rating = new RatingsCommand(video).observe();
Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe();
return Observable.zip(bookmark, rating, metadata, (b, r, m) -> {
return combineVideoData(video, b, r, m);
});
});
});
Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> {
return s.getDataAsMap();
});
return Observable.merge(catalog, social);
}).flatMap(data -> {
return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER);
});
return new UserCommand(userId).observe().flatMap(user -> {
Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe()
.flatMap(catalogList -> {
return catalogList.videos().<Map<String, Object>> flatMap(video -> {
Observable<Bookmark> bookmark = new BookmarkCommand(video).observe();
Observable<Rating> rating = new RatingsCommand(video).observe();
Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe();
return Observable.zip(bookmark, rating, metadata, (b, r, m) -> {
return combineVideoData(video, b, r, m);
});
});
});
Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> {
return s.getDataAsMap();
});
return Observable.merge(catalog, social);
}).flatMap(data -> {
return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER);
});
return new UserCommand(userId).observe().flatMap(user -> {
Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe()
.flatMap(catalogList -> {
return catalogList.videos().<Map<String, Object>> flatMap(video -> {
Observable<Bookmark> bookmark = new BookmarkCommand(video).observe();
Observable<Rating> rating = new RatingsCommand(video).observe();
Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe();
return Observable.zip(bookmark, rating, metadata, (b, r, m) -> {
return combineVideoData(video, b, r, m);
});
});
});
Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> {
return s.getDataAsMap();
});
return Observable.merge(catalog, social);
}).flatMap(data -> {
return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER);
});
return new UserCommand(userId).observe().flatMap(user -> {
Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe()
.flatMap(catalogList -> {
return catalogList.videos().<Map<String, Object>> flatMap(video -> {
Observable<Bookmark> bookmark = new BookmarkCommand(video).observe();
Observable<Rating> rating = new RatingsCommand(video).observe();
Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe();
return Observable.zip(bookmark, rating, metadata, (b, r, m) -> {
return combineVideoData(video, b, r, m);
});
});
});
Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> {
return s.getDataAsMap();
});
return Observable.merge(catalog, social);
}).flatMap(data -> {
return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER);
});
return new UserCommand(userId).observe().flatMap(user -> {
Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe()
.flatMap(catalogList -> {
return catalogList.videos().<Map<String, Object>> flatMap(video -> {
Observable<Bookmark> bookmark = new BookmarkCommand(video).observe();
Observable<Rating> rating = new RatingsCommand(video).observe();
Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe();
return Observable.zip(bookmark, rating, metadata, (b, r, m) -> {
return combineVideoData(video, b, r, m);
});
});
});
Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> {
return s.getDataAsMap();
});
return Observable.merge(catalog, social);
}).flatMap(data -> {
return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER);
});
return new UserCommand(userId).observe().flatMap(user -> {
Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe()
.flatMap(catalogList -> {
return catalogList.videos().<Map<String, Object>> flatMap(video -> {
Observable<Bookmark> bookmark = new BookmarkCommand(video).observe();
Observable<Rating> rating = new RatingsCommand(video).observe();
Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe();
return Observable.zip(bookmark, rating, metadata, (b, r, m) -> {
return combineVideoData(video, b, r, m);
});
});
});
Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> {
return s.getDataAsMap();
});
return Observable.merge(catalog, social);
}).flatMap(data -> {
return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER);
});
return new UserCommand(userId).observe().flatMap(user -> {
Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe()
.flatMap(catalogList -> {
return catalogList.videos().<Map<String, Object>> flatMap(video -> {
Observable<Bookmark> bookmark = new BookmarkCommand(video).observe();
Observable<Rating> rating = new RatingsCommand(video).observe();
Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe();
return Observable.zip(bookmark, rating, metadata, (b, r, m) -> {
return combineVideoData(video, b, r, m);
});
});
});
Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> {
return s.getDataAsMap();
});
return Observable.merge(catalog, social);
}).flatMap(data -> {
return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER);
});
+
1.3.x (current production)
1.4 Release Candidate (available now)
- support for fully non-blocking
1.4.0 Final (coming months)
0.19.x (current production)
0.20 Release Candidates (coming weeks)
- the “backpressure” release
0.20.0 Final
1.0 Release Candidates (Summer 2014)
- no more breaking changes
1.0.0 Final (Summer/Fall 2014)
github.com/Netflix/RxJava github.com/ReactiveX/RxJava
Version 1.x to be released
on Maven Central with
groupId io.reactivex.*
github.com/Netflix/RxJava github.com/ReactiveX/RxJava
github.com/ReactiveX/RxScala
github.com/ReactiveX/RxGroovy
github.com/ReactiveX/RxClojure
github.com/ReactiveX/RxKotlin
github.com/ReactiveX/RxJRuby
github.com/ReactiveX/RxAndroid
etc ...
Version 1.x to be released
on Maven Central with
groupId io.reactivex.*
Along the way we started thinking
about non-blocking IO ...
WSPerfLab
https://github.com/Netflix-Skunkworks/WSPerfLab
WSPerfLab
https://github.com/Netflix-Skunkworks/WSPerfLab
Best case latency for response is ~155ms
RxNetty Performance
client:
wrk -t 4 -c 400
server CPUs
~2% idle
NOTE: It is still
early days for
RxNetty tuning;
more to come
Tuning for an acceptable latency
distribution
client: ab
server CPU
usage varies
with load
RxNetty vs Tomcat
Event loop model more efficient than thread pools:
● Reduces thread CPU overheads
● Reduced thread lock contention
● Better work scheduling: platform chooses, instead of the
kernel scheduling threads
● Warmer CPU caches and memory locality on NUMA:
event worker threads can have better CPU affinity
RxNetty Micro Benchmarking
Server: AWS c3.xlarge, tuned to reduce perturbations
Client: Multi-threaded (wrk -t 4 -c 100/400), 1 min warmup
● Sufficient load to exhaust CPU capacity.
Active Benchmarking Methodology:
● Tools: sysstat, perf_events, SystemTap, flame graphs, …
● USE Method, static performance tuning, etc.
● Target analyzed during benchmark confirm target results
and identify (and tune) true limiters.
Approaching light speed...
Hello World
● All platforms are <100us for Hello World, so their CPU
overheads are already negligible for this workload.
○ Consider application compute times of >1ms
● Hence testing “Hello Netflix” as well: a basic Netflix
service Hello World with dependency requests.
● Although, Hello World max latency (not pictured) was
still much higher for Tomcat...
Visualizing Tomcat Overheads
● Flame graph of
Java CPU time
for Hello World
benchmark
● Thread and I/O
management
overheads
Visualizing RxNetty Overheads
● Flame graph of Java CPU
time for Hello World
● Time in read() and write()
(doing I/O; ie, doing “work”)
dominates
● Flame graphs also studied
of kernel and user-time
● Many improvements found
and fixed
Blog post forthcoming… Keywords:
● Oracle JDK 1.8.0 (others tried); Xmx & Xms; different
GCs and settings, eg -XX:+UseConcMarkSweepGC
● Apache-tomcat 7.0.54: tested BIO, NIO, APR;
maxThreads=150 or 512; maxQueueSize=up to 400;
acceptCount=up to 100; disabled access log, ...
● Node.js 0.6.12 with clustering (faster than 0.10/0.11)
● vert.x 2.1 with -instances 4
● Java profilers: Google lightweight java profiler; JFR; …
● perf_events; SystemTap; flame graphs, ...
RxNetty & Karyon 2.0
@NiteshKant
Netflix IPC Stack (1.0)
A
p
a
c
h
e
H
T
T
P
C
l
i
e
n
t
Eureka (Service Registry)
Server (Karyon)
Apache
Tomcat
Client
H
y
s
t
r
i
x
E
V
C
a
c
h
e
Ribbon
Load
Balancing
Eureka
Integration
Metrics
(Servo)
Bootstrapping (Governator)
Metrics (Servo)
Admin ConsoleHTTP
Eureka Integration
Registration
Fetch Registry
A Blocking Architecture
Netflix IPC Stack (2.0)
Client (Ribbon 2.0)
Eureka (Service Registry)
Server (Karyon)
Ribbon Transport
Load
Balancing
Eureka
Integration
Metrics
(Servo)
Bootstrapping (Governator)
Metrics (Servo)
Admin Console
HTTP
Eureka Integration
Registration
Fetch Registry
Ribbon
Hystrix
EVCache
R
x
N
e
t
t
y
RxNetty
UDP
TCP
WebSockets
SSE
A Completely Reactive
Architecture
“We want an extremely performant IPC library”
Heard this before?
Reinventing The Wheel?
Image Courtesy: Oxford Creativity
Finagle
Vert.x
Ratpack
Tons of
Netty based
Frameworks?
On the lookout …..
● Low level control.
○ Traffic Shaping. (Zuul)
○ Backpressure.
● Netflix “fit”
○ Reactive programming model.
○ Netflix Components (Eureka, Archaius, Governator, etc.)
RxNetty
Reactive Extensions To Netty
Nucleus of Netflix’s IPC stack
Powering Ribbon 2.0 & Karyon
2.0
https://github.com/Netflix/RxNetty
Example (Server Sent Events)
RxNetty.createHttpServer(8887, (request, response) -> {
return Observable.interval(1, TimeUnit.SECONDS)
.flatMap(interval -> {
return response.writeAndFlush(new ServerSentEvent(...));
});
}, PipelineConfigurators.<ByteBuf>sseServerConfigurator()).start();
Server
Client
RxNetty.<ByteBuf, ServerSentEvent>createHttpClient("127.0.0.1", 8887,
PipelineConfigurators.sseClientConfigurator())
.submit(HttpClientRequest.<ByteBuf>createGet("/"))
.flatMap(response -> response.getContent())
.toBlocking().forEach(event -> System.out.println(event))
data: interval: 0
data: interval: 1
data: interval: 2
data: interval: 3
Output …...
data: interval: 4
data: interval: 5
Example (Stream Aggregation)
RxNetty.createHttpServer(8887, (request, response) -> {
return Observable.interval(1, TimeUnit.SECONDS)
.flatMap(interval -> {
return response.writeAndFlush(new ServerSentEvent(...));
});
}, PipelineConfigurators.<ByteBuf>sseServerConfigurator()).start();
{ } *3
Example (Stream Aggregation)
Observable.merge(RxNetty.<ByteBuf, ServerSentEvent>createHttpClient("127.0.0.1", 8887...),
RxNetty.<ByteBuf, ServerSentEvent>createHttpClient("127.0.0.1", 8888...),
RxNetty.<ByteBuf, ServerSentEvent>createHttpClient("127.0.0.1", 8889...))
).toBlocking().forEach(event -> System.out.println(event))
RxNetty.createHttpServer(8887, ...).start(); RxNetty.createHttpServer(8888, ...).start(); RxNetty.createHttpServer(8889, ...).start();
data: interval (8887): 0
data: interval (8888): 0
data: interval (8887): 1
data: interval (8887): 2
Output …...
data: interval (8889): 0
data: interval (8888): 1
Karyon 2.0
● Adds Netflix constructs (governator, eureka, archaius,
etc.) on RxNetty.
● Provides extensions (servlet, jersey, etc.) to RxNetty.
● More palatable to application developers.
Example
@ArchaiusBootstrap
@KaryonBootstrap(name = "hello-netflix-oss")
@Modules(include = {HelloNossApp.KaryonJerseyModuleImpl.class, KaryonWebAdminModule.class, KaryonEurekaModule.class})
public final class HelloNossApp {
public static class KaryonJerseyModuleImpl extends KaryonJerseyModule {
protected void configure() {
super.configure();
bind(AuthenticationService.class).to(AuthenticationServiceImpl.class);
}
public int serverPort() { return 8888; }
public int shutdownPort() { return 8899; }
public void configureInterceptors(GovernatorHttpInterceptorSupport<ByteBuf, ByteBuf> interceptorSupport) {
interceptorSupport.forUri("/hello").interceptIn(AuthInterceptor.class);
}
}
}
Ribbon 2
Allen Wang
● Tendency to become “fat” with boilerplate
code
● Hystrix integration
● Go “async”
● “Declare” a client, rather than “write” a client
Ribbon 2.0 - Motivation
Ribbon 2.0: Let’s tie ‘em up
Ribbon 2.0 - New “ribbon” module
● Template support for building HTTP request
● Rx style non-blocking and blocking APIs
● Hystrix built-in for fault tolerance
● Pluggable cache access with EVCache
implementation
● Annotation based client creation as an
alternative
Ribbon 2.0 - Annotation Example
public interface MovieService {
RibbonRequest<Recommendations> recommendationsByUserId(@Var("userId") String
userId);
}
@TemplateName(“recommendations”)
@Http(method = HttpMethod.GET, uriTemplate="/users/{userId}/recommendations")
@Hystrix(fallbackHandler = RecommendationFallbackHandler.class)
@EvCache(name = "movie-rec", appName = "movieService", cacheKeyTemplate =
"{userId}")
MovieService movieService = Ribbon.from(MovieService.class);
Observable<Recommendations> result =
movieService.recommendationsByUserId(“user1”)
.toObservable();
Ribbon 2: Template Example
HttpResourceGroup movieService = Ribbon.createHttpResourceGroup("movieService");
HttpRequestTemplate<ByteBuf> template1 =
movieService.newRequestTemplate("recommendationsByUserId", ByteBuf.class)
.withMethod("GET")
.withUriTemplate("/users/{userId}/recommendations")
.withFallbackProvider(new RecommendationServiceFallbackHandler());
RibbonRequest<ByteBuf> request = template1.requestBuilder()
.withRequestProperty("userId", “user1”).build();
Observable<ByteBuf> result = request.toObservable(); // non blocking
ByteBuf result = request.execute(); // blocking
Ribbon 2.0 - Other New Features
● Ribbon’s async module - “ribbon-transport”
○ HTTP, TCP and UDP clients on top of RxNetty with
load balancing capability
● New load balancing features
○ Command pattern load balancing APIs implemented
with Rx for easy integration for third party client
○ Shuffle sharding server list for fault isolation
Reactive outside Netflix
Retrofit
Jake Wharton
Retrofit
Example:
GitHub API
List Contributors
GET /repos/:owner/:repo/contributors
Retrofit
GET /repos/:owner/:repo/contributors
interface GitHub {
List<Contributor> contributors(
String owner,
String repo);
}
class Contributor {
String login;
long contributions;
}
Retrofit
GET /repos/:owner/:repo/contributors
interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
List<Contributor> contributors(
String owner,
String repo);
}
Retrofit
GET /repos/:owner/:repo/contributors
interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
List<Contributor> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
Retrofit
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com/")
.build();
GitHub gitHub = restAdapter.create(GitHub.class);
List<Contributor> contributors =
gitHub.contributors("netflix", "rxjava");
Retrofit
List<Contributor> contributors =
gitHub.contributors("netflix", "rxjava");
for (Contributor c : contributors) {
println(c.login + 't' + c.contributions);
}
1483 benjchristensen
225 zsxwing
167 samuelgruetter
146 jmhofer
137 akarnokd
105 DavidMGross
102 AppliedDuality
...
Retrofit
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://drive.google.com/api/")
.setConverter(new ProtoConverter())
.build();
Retrofit
interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
List<Contributor> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
Retrofit
interface GitHub {
@GET("/repos/{owner}/{repo}/contributors?anon=true")
List<Contributor> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
Retrofit
interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
List<Contributor> contributors(
@Path("owner") String owner,
@Path("repo") String repo,
@Query("anon") boolean includeAnonymous);
}
Retrofit
interface GitHub {
@POST("/repos/{owner}/{repo}/hooks")
Response createHook(
@Path("owner") String owner,
@Path("repo") String repo,
@Body Hook hook);
}
class Hook {
String name;
Map<String, Object> config;
List<String> events;
boolean active;
}
Retrofit
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://drive.google.com/api/")
.setConverter(new ProtoConverter())
.setClient(new OkClient())
.build();
Retrofit
OkHttpClient client = new OkHttpClient();
client.setProtocols(Arrays.asList(HTTP_2));
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://drive.google.com/api/")
.setConverter(new ProtoConverter())
.setClient(new OkClient(client))
.build();
Retrofit
● Form URL encoding
● Response streaming
● Request interceptors
● Dynamic headers
● Android
● Multipart
● Logging
● Mock RestAdapter
● Asynchronous invoke
● AppEngine
...and more!
Retrofit + RxJava
interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
List<Contributor> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
Retrofit + RxJava
interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Observable<List<Contributor>> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
Retrofit + RxJava
gitHub.contributors("netflix", "rxjava")
.lift(flattenList())
.forEach(c -> println(c.login + 't' + c.contributions));
1483 benjchristensen
225 zsxwing
167 samuelgruetter
146 jmhofer
137 akarnokd
105 DavidMGross
102 AppliedDuality
...
Retrofit + RxJava
interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Observable<List<Contributor>> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
@GET("/users/{user}")
Observable<User> user(
@Path("user") String user);
}
Retrofit + RxJava
gitHub.contributors("netflix", "rxjava")
.lift(flattenList())
.flatMap(c -> gitHub.user(c.login))
.forEach(user -> println(user.name));
Ben Christensen
Shixiong Zhu
null
Joachim Hofer
null
David Gross
null
...
Retrofit + RxJava
gitHub.contributors("netflix", "rxjava")
.lift(flattenList())
.flatMap(c -> gitHub.user(c.login))
.filter(user -> user.name != null)
.forEach(user -> println(user.name));
Ben Christensen
Shixiong Zhu
Joachim Hofer
David Gross
Matthias Käppler
Justin Ryan
Mairbek Khadikov
...
Retrofit + RxJava
interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Observable<List<Contributor>> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
@GET("/users/{user}/starred")
Observable<List<Repo>> starred(
@Path("user") String user);
}
Retrofit + RxJava
gitHub.contributors("netflix", "rxjava")
.lift(flattenList())
.flatMap(c -> gitHub.starred(c.login))
.lift(flattenList())
.groupBy(r -> r.full_name)
.flatMap(g -> g.count().map(c -> c + "t" + g.getKey()))
.toSortedList((a, b) -> b.compareTo(a))
.lift(flattenList())
.take(8)
.forEach(Main::println);
Retrofit + RxJava
7 Netflix/RxJava
2 twitter/finagle
2 scala/scala
2 mbostock/d3
2 kpelykh/docker-java
2 Netflix/zuul
2 Netflix/feign
2 Netflix/archaius
Retrofit + RxJava
gitHub.contributors("square", "retrofit")
.lift(flattenList())
.flatMap(c -> gitHub.starred(c.login))
.lift(flattenList())
.groupBy(r -> r.full_name)
.flatMap(g -> g.count().map(c -> c + "t" + g.getKey()))
.toSortedList((a, b) -> b.compareTo(a))
.lift(flattenList())
.take(8)
.forEach(Main::println);
gitHub.contributors("square", "retrofit")
.lift(flattenList())
.flatMap(c -> gitHub.starred(c.login))
.lift(flattenList())
.filter(r -> !r.full_name.startsWith("square/"))
.groupBy(r -> r.full_name)
.flatMap(g -> g.count().map(c -> c + "t" + g.getKey()))
.toSortedList((a, b) -> b.compareTo(a))
.lift(flattenList())
.take(8)
.forEach(Main::println);
Retrofit + RxJava
Retrofit + RxJava
4 frankiesardo/auto-parcel
4 Comcast/FreeFlow
3 xxv/android-lifecycle
3 robolectric/robolectric
3 inmite/android-butterknife-zelezny
3 google/auto
3 facebook/rebound
3 etsy/AndroidStaggeredGrid
3 Netflix/RxJava
Retrofit
square.github.io/retrofit
Couchbase
Matt Ingenthron
Couchbase is...
Document-oriented (JSON) database ...
Low latency & high throughput …
Highly available and scalable ...
Motivations with Couchbase Java
➢ Simplify ...
➢ Even *more* performance
➢ Build for the JVM, not for the Java language
○ Have Scala, JRuby already being worked on
History of Concurrency
Core Java component, spymemcached, has
used Futures since 2006 or so.
➢ Always been ahead of most other database
like clients, however…
➢ Difficult for developers to code against
○ Dumb benchmarks turn into FAQs
while (true) { client.set("foo", "bar") };
while (true) { client.set("foo", "bar") };
Signature:
public OperationFuture<java.lang.Boolean> set(java.lang.String key,
java.lang.Object value);
while (true) { client.set("foo", "bar").get() };
What we’re Building On
➢ A set of new components
○ RxJava (both internal and public interface)
○ Netty (internal only)
○ LMAX Disruptor
RxJava for Couchbase
➢ Will be part of the client’s public API
○ Helps us support Java 8, but is also backward
compatible
■ Generally get a great Java 8 experience for free!
➢ Also using RxJava extensively internally
○ Breaking the project into core and language façade
helps build toward Scala and others
Getting Referenced Elements
client.asyncGet("posts::1").addListener(future -> {
if (future.isDone() && !future.isCancelled()) {
String content = (String) future.get();
List<String> ids =
comments_ids_from_json(content);
int i = 0;
for (String id : ids) {
if (i++ == 5) {
break;
}
client.asyncGet(id).addListener(future1 -> {
if (future1.isDone() && !future1.isCancelled()) {
System.out.println(future1.get());
}
});
}
}
});
Getting Referenced Elements Rx Way
bucket
.get("posts::1")
.map(document -> document.content().getArray("comments"))
.flatMap(comments -> Observable.from(comments.toList()))
.take(5)
.filter(o -> o instanceof String)
.flatMap(o -> bucket.get((String) o))
.subscribe(doc -> System.out.println(doc.content()));
Beauty of Error Handling
return super.registerBucket(name, password).flatMap(new Func1<Boolean,
Observable<BucketStreamingResponse>>() {
@Override
public Observable<BucketStreamingResponse> call(Boolean aBoolean) {
return cluster().send(new BucketStreamingRequest(TERSE_PATH, name, password));
}
}).onErrorResumeNext(new Func1<Throwable, Observable<BucketStreamingResponse>>() {
@Override
public Observable<BucketStreamingResponse> call(Throwable throwable) {
return cluster().send(new BucketStreamingRequest(VERBOSE_PATH, name, password));
}
})
Couchbase
React to our Dev Preview 2!
Michael Nitschinger’s blog:
http://blog.couchbase.com/couchbase-java-sdk-200-developer-preview-2
Five Minutes of Futures
Will Sargent, Typesafe
Reactive Interface In Theory
Looks like:
● Responsive?
● Scalable?
● Resilient?
● Event-Driven?
Reactive Interface in Practice
Really looks like this:
trait FooService {
def find(fooId:FooID) : Future[Option[Foo]]
}
Plain English
“Non-blocking” / “Async”
means either Future[T] or Actor
model
Choices
To Akka, or Not to Akka?
Akka with Futures
Akka to Future:
val myFuture = actorRef ? message
Future to Akka:
futureStuff pipeTo actorRef
Assuming a Services based API
val fooFuture = fooService.get(1)
val barFuture = barService.get(2)
val quuxFuture = quuxService.get(3)
...Simple, right?
Not so fast
val fooFuture = fooService.get(1)
val barFuture = barService.get(foo.barId)
val quuxFuture = quuxService.get(bar.quuxId)
...wat.
FLATMAP THAT
fooService.get(1).map { maybeFoo =>
maybeFoo.flatMap { foo =>
val barFuture = barService.get(foo.barId)
// do the same for bar & quux
}
}
For comprehensions!
for {
maybeFoo <- fooService.get(1)
} yield {
for { // Option / Future does not compose
foo <- maybeFoo
} yield ...
}
Scala Async!
async {
val maybeFoo = await(fooService.get(1))
maybeFoo.flatMap { foo =>
val bar = await(barService.get(2))
}
}
Scala Async Sadness
COMPILE ERROR.
“await must not be used inside a closure nested
within an async block” == no flatMap of that.
Monads don’t compose
But before reaching for readers/transformers:
● Use small methods
● Short circuit
● Use loan patterns
Use Small Methods
def foo2bar(ff:Future[Foo]) : Future[Bar]
Short Circuit
implicit def flatten[A](fofoa: Future[Option
[Future[Option[A]]]]): Future[Option[A]] = fofoa.
flatMap(_.getOrElse(Future.successful(None)))
Loan Pattern
def getFuture[T](futureOptionBlock: Future[Option[T]])(foundBlock: (T =>
Future[Result])): Future[Result] = {
futureOptionBlock.flatMap {
case Some(found) =>
foundBlock(found)
case None =>
Future.successful(NotFound)
}
}
What’s next?
Demos, food and drinks!
August 20th - NetflixOSS and Cloud Security

More Related Content

What's hot

Session 1 - CloudStack Plugin Structure and Implementation (2013.Q3)
Session 1 - CloudStack Plugin Structure and Implementation (2013.Q3)Session 1 - CloudStack Plugin Structure and Implementation (2013.Q3)
Session 1 - CloudStack Plugin Structure and Implementation (2013.Q3)
tcloudcomputing-tw
 
Orchestration & provisioning
Orchestration & provisioningOrchestration & provisioning
Orchestration & provisioning
buildacloud
 
Session 2 - CloudStack Usage and Application (2013.Q3)
Session 2 - CloudStack Usage and Application (2013.Q3)Session 2 - CloudStack Usage and Application (2013.Q3)
Session 2 - CloudStack Usage and Application (2013.Q3)
tcloudcomputing-tw
 

What's hot (20)

Microservices with Micronaut
Microservices with MicronautMicroservices with Micronaut
Microservices with Micronaut
 
Netflix oss season 1 episode 3
Netflix oss season 1 episode 3 Netflix oss season 1 episode 3
Netflix oss season 1 episode 3
 
Netflix Open Source Meetup Season 3 Episode 2
Netflix Open Source Meetup Season 3 Episode 2Netflix Open Source Meetup Season 3 Episode 2
Netflix Open Source Meetup Season 3 Episode 2
 
Monitoring, the Prometheus Way - Julius Voltz, Prometheus
Monitoring, the Prometheus Way - Julius Voltz, Prometheus Monitoring, the Prometheus Way - Julius Voltz, Prometheus
Monitoring, the Prometheus Way - Julius Voltz, Prometheus
 
Netflix Open Source Meetup Season 4 Episode 2
Netflix Open Source Meetup Season 4 Episode 2Netflix Open Source Meetup Season 4 Episode 2
Netflix Open Source Meetup Season 4 Episode 2
 
OpenCensus with Prometheus and Kubernetes
OpenCensus with Prometheus and KubernetesOpenCensus with Prometheus and Kubernetes
OpenCensus with Prometheus and Kubernetes
 
S3, Cassandra or Outer Space? Dumping Time Series Data using Spark - Demi Be...
S3, Cassandra or Outer Space? Dumping Time Series Data using Spark  - Demi Be...S3, Cassandra or Outer Space? Dumping Time Series Data using Spark  - Demi Be...
S3, Cassandra or Outer Space? Dumping Time Series Data using Spark - Demi Be...
 
Openstack Overview
Openstack OverviewOpenstack Overview
Openstack Overview
 
QCon NYC: Distributed systems in practice, in theory
QCon NYC: Distributed systems in practice, in theoryQCon NYC: Distributed systems in practice, in theory
QCon NYC: Distributed systems in practice, in theory
 
Session 1 - CloudStack Plugin Structure and Implementation (2013.Q3)
Session 1 - CloudStack Plugin Structure and Implementation (2013.Q3)Session 1 - CloudStack Plugin Structure and Implementation (2013.Q3)
Session 1 - CloudStack Plugin Structure and Implementation (2013.Q3)
 
Nashorn: JavaScript that doesn't suck - Tomer Gabel, Wix
Nashorn: JavaScript that doesn't suck - Tomer Gabel, WixNashorn: JavaScript that doesn't suck - Tomer Gabel, Wix
Nashorn: JavaScript that doesn't suck - Tomer Gabel, Wix
 
Optimizing {Java} Application Performance on Kubernetes
Optimizing {Java} Application Performance on KubernetesOptimizing {Java} Application Performance on Kubernetes
Optimizing {Java} Application Performance on Kubernetes
 
Container orchestration: the cold war - Giulio De Donato - Codemotion Rome 2017
Container orchestration: the cold war - Giulio De Donato - Codemotion Rome 2017Container orchestration: the cold war - Giulio De Donato - Codemotion Rome 2017
Container orchestration: the cold war - Giulio De Donato - Codemotion Rome 2017
 
Orchestration & provisioning
Orchestration & provisioningOrchestration & provisioning
Orchestration & provisioning
 
Kubernetes #6 advanced scheduling
Kubernetes #6   advanced schedulingKubernetes #6   advanced scheduling
Kubernetes #6 advanced scheduling
 
(BDT318) How Netflix Handles Up To 8 Million Events Per Second
(BDT318) How Netflix Handles Up To 8 Million Events Per Second(BDT318) How Netflix Handles Up To 8 Million Events Per Second
(BDT318) How Netflix Handles Up To 8 Million Events Per Second
 
Distributed Locking in Kubernetes
Distributed Locking in KubernetesDistributed Locking in Kubernetes
Distributed Locking in Kubernetes
 
Netflix at-disney-09-26-2014
Netflix at-disney-09-26-2014Netflix at-disney-09-26-2014
Netflix at-disney-09-26-2014
 
"[WORKSHOP] K8S for developers", Denis Romanuk
"[WORKSHOP] K8S for developers", Denis Romanuk"[WORKSHOP] K8S for developers", Denis Romanuk
"[WORKSHOP] K8S for developers", Denis Romanuk
 
Session 2 - CloudStack Usage and Application (2013.Q3)
Session 2 - CloudStack Usage and Application (2013.Q3)Session 2 - CloudStack Usage and Application (2013.Q3)
Session 2 - CloudStack Usage and Application (2013.Q3)
 

Viewers also liked

Netflix oss season 2 episode 1 - meetup Lightning talks
Netflix oss   season 2 episode 1 - meetup Lightning talksNetflix oss   season 2 episode 1 - meetup Lightning talks
Netflix oss season 2 episode 1 - meetup Lightning talks
Ruslan Meshenberg
 

Viewers also liked (6)

Netflix Open Source Meetup Season 4 Episode 1
Netflix Open Source Meetup Season 4 Episode 1Netflix Open Source Meetup Season 4 Episode 1
Netflix Open Source Meetup Season 4 Episode 1
 
NetflixOSS Meetup season 3 episode 1
NetflixOSS Meetup season 3 episode 1NetflixOSS Meetup season 3 episode 1
NetflixOSS Meetup season 3 episode 1
 
Netflix oss season 2 episode 1 - meetup Lightning talks
Netflix oss   season 2 episode 1 - meetup Lightning talksNetflix oss   season 2 episode 1 - meetup Lightning talks
Netflix oss season 2 episode 1 - meetup Lightning talks
 
20140708 - Jeremy Edberg: How Netflix Delivers Software
20140708 - Jeremy Edberg: How Netflix Delivers Software20140708 - Jeremy Edberg: How Netflix Delivers Software
20140708 - Jeremy Edberg: How Netflix Delivers Software
 
Programação functional reativa: lidando com código assíncrono
Programação functional reativa: lidando com código assíncronoProgramação functional reativa: lidando com código assíncrono
Programação functional reativa: lidando com código assíncrono
 
Spring Boot + Netflix Eureka
Spring Boot + Netflix EurekaSpring Boot + Netflix Eureka
Spring Boot + Netflix Eureka
 

Similar to NetflixOSS season 2 episode 2 - Reactive / Async

Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 

Similar to NetflixOSS season 2 episode 2 - Reactive / Async (20)

Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
 
Tech Talk #4 : RxJava and Using RxJava in MVP - Dương Văn Tới
Tech Talk #4 : RxJava and Using RxJava in MVP - Dương Văn TớiTech Talk #4 : RxJava and Using RxJava in MVP - Dương Văn Tới
Tech Talk #4 : RxJava and Using RxJava in MVP - Dương Văn Tới
 
Compact and safely: static DSL on Kotlin
Compact and safely: static DSL on KotlinCompact and safely: static DSL on Kotlin
Compact and safely: static DSL on Kotlin
 
Rx java in action
Rx java in actionRx java in action
Rx java in action
 
Angular2 rxjs
Angular2 rxjsAngular2 rxjs
Angular2 rxjs
 
Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015
 
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
 
code for quiz in my sql
code for quiz  in my sql code for quiz  in my sql
code for quiz in my sql
 
Functional UIs with Java 8 and Vaadin JavaOne2014
Functional UIs with Java 8 and Vaadin JavaOne2014Functional UIs with Java 8 and Vaadin JavaOne2014
Functional UIs with Java 8 and Vaadin JavaOne2014
 
MiamiJS - The Future of JavaScript
MiamiJS - The Future of JavaScriptMiamiJS - The Future of JavaScript
MiamiJS - The Future of JavaScript
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
Presentation Android Architecture Components
Presentation Android Architecture ComponentsPresentation Android Architecture Components
Presentation Android Architecture Components
 
Practical RxJava for Android
Practical RxJava for AndroidPractical RxJava for Android
Practical RxJava for Android
 
[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data product[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data product
 
Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2
 
Androidaop 170105090257
Androidaop 170105090257Androidaop 170105090257
Androidaop 170105090257
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Example R usage for oracle DBA UKOUG 2013
Example R usage for oracle DBA UKOUG 2013Example R usage for oracle DBA UKOUG 2013
Example R usage for oracle DBA UKOUG 2013
 
Testing Android apps based on Dagger and RxJava Droidcon UK
Testing Android apps based on Dagger and RxJava Droidcon UKTesting Android apps based on Dagger and RxJava Droidcon UK
Testing Android apps based on Dagger and RxJava Droidcon UK
 
Building Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaBuilding Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJava
 

More from Ruslan Meshenberg

NetflixOSS meetup lightning talks and roadmap
NetflixOSS meetup lightning talks and roadmapNetflixOSS meetup lightning talks and roadmap
NetflixOSS meetup lightning talks and roadmap
Ruslan Meshenberg
 

More from Ruslan Meshenberg (10)

NetflixOSS Meetup season 3 episode 2
NetflixOSS Meetup season 3 episode 2NetflixOSS Meetup season 3 episode 2
NetflixOSS Meetup season 3 episode 2
 
Netflix oss past-present-future
Netflix oss   past-present-futureNetflix oss   past-present-future
Netflix oss past-present-future
 
Dev309 from asgard to zuul - netflix oss-final
Dev309  from asgard to zuul - netflix oss-finalDev309  from asgard to zuul - netflix oss-final
Dev309 from asgard to zuul - netflix oss-final
 
OSS Think Tank - NetflixOSS - OSS as a Competitive Differentiator
OSS Think Tank - NetflixOSS - OSS as a Competitive DifferentiatorOSS Think Tank - NetflixOSS - OSS as a Competitive Differentiator
OSS Think Tank - NetflixOSS - OSS as a Competitive Differentiator
 
Arc305 how netflix leverages multiple regions to increase availability an i...
Arc305 how netflix leverages multiple regions to increase availability   an i...Arc305 how netflix leverages multiple regions to increase availability   an i...
Arc305 how netflix leverages multiple regions to increase availability an i...
 
Svc 202-netflix-open-source
Svc 202-netflix-open-sourceSvc 202-netflix-open-source
Svc 202-netflix-open-source
 
NetflixOSS meetup lightning talks and roadmap
NetflixOSS meetup lightning talks and roadmapNetflixOSS meetup lightning talks and roadmap
NetflixOSS meetup lightning talks and roadmap
 
NetflixOSS Open House Lightning talks
NetflixOSS Open House Lightning talksNetflixOSS Open House Lightning talks
NetflixOSS Open House Lightning talks
 
re:Invent 2012 Optimizing Cassandra
re:Invent 2012 Optimizing Cassandrare:Invent 2012 Optimizing Cassandra
re:Invent 2012 Optimizing Cassandra
 
The Netflix Open Source Platform
The Netflix Open Source PlatformThe Netflix Open Source Platform
The Netflix Open Source Platform
 

Recently uploaded

Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Christo Ananth
 
AKTU Computer Networks notes --- Unit 3.pdf
AKTU Computer Networks notes ---  Unit 3.pdfAKTU Computer Networks notes ---  Unit 3.pdf
AKTU Computer Networks notes --- Unit 3.pdf
ankushspencer015
 

Recently uploaded (20)

Coefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxCoefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptx
 
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
 
DJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINE
DJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINEDJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINE
DJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINE
 
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
 
BSides Seattle 2024 - Stopping Ethan Hunt From Taking Your Data.pptx
BSides Seattle 2024 - Stopping Ethan Hunt From Taking Your Data.pptxBSides Seattle 2024 - Stopping Ethan Hunt From Taking Your Data.pptx
BSides Seattle 2024 - Stopping Ethan Hunt From Taking Your Data.pptx
 
High Profile Call Girls Nagpur Isha Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Isha Call 7001035870 Meet With Nagpur EscortsHigh Profile Call Girls Nagpur Isha Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Isha Call 7001035870 Meet With Nagpur Escorts
 
Introduction to Multiple Access Protocol.pptx
Introduction to Multiple Access Protocol.pptxIntroduction to Multiple Access Protocol.pptx
Introduction to Multiple Access Protocol.pptx
 
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur EscortsHigh Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
 
UNIT-III FMM. DIMENSIONAL ANALYSIS
UNIT-III FMM.        DIMENSIONAL ANALYSISUNIT-III FMM.        DIMENSIONAL ANALYSIS
UNIT-III FMM. DIMENSIONAL ANALYSIS
 
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
 
Russian Call Girls in Nagpur Grishma Call 7001035870 Meet With Nagpur Escorts
Russian Call Girls in Nagpur Grishma Call 7001035870 Meet With Nagpur EscortsRussian Call Girls in Nagpur Grishma Call 7001035870 Meet With Nagpur Escorts
Russian Call Girls in Nagpur Grishma Call 7001035870 Meet With Nagpur Escorts
 
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdfONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
 
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCollege Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
 
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
 
University management System project report..pdf
University management System project report..pdfUniversity management System project report..pdf
University management System project report..pdf
 
Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...
Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...
Sheet Pile Wall Design and Construction: A Practical Guide for Civil Engineer...
 
Booking open Available Pune Call Girls Koregaon Park 6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Koregaon Park  6297143586 Call Hot Ind...Booking open Available Pune Call Girls Koregaon Park  6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Koregaon Park 6297143586 Call Hot Ind...
 
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
 
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
 
AKTU Computer Networks notes --- Unit 3.pdf
AKTU Computer Networks notes ---  Unit 3.pdfAKTU Computer Networks notes ---  Unit 3.pdf
AKTU Computer Networks notes --- Unit 3.pdf
 

NetflixOSS season 2 episode 2 - Reactive / Async

  • 1. Season 2 Episode 2 July 9, 2014
  • 2. Evening Outline Lightning Talks: ● Reactive / Rx ● RxJava ● RxNetty ● Ribbon 2.0 ● Karyon 2.0 Guest Speakers ● Jake Wharton, Square ● Matt Ingenthron, Couchbase ● Will Sargent, Typesafe
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 12. Clojure Scala Groovy JRuby Java 8 (-> (Observable/from ["one" "two" "three"]) (.take 2) (.subscribe (rx/action [arg] (println arg)))) Observable("one", "two", "three") .take(2) .subscribe((arg: String) => { println(arg) }) Observable.from("one", "two", "three") .take(2) .subscribe(lambda { |arg| puts arg }) Observable.from("one", "two", "three") .take(2) .subscribe({arg -> println(arg)}) Observable.from("one", "two", "three") .take(2) .subscribe(System.out::println);
  • 13. return new UserCommand(userId).observe().flatMap(user -> { Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); return Observable.merge(catalog, social); }).flatMap(data -> { return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER); });
  • 14. return new UserCommand(userId).observe().flatMap(user -> { Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); return Observable.merge(catalog, social); }).flatMap(data -> { return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER); });
  • 15. return new UserCommand(userId).observe().flatMap(user -> { Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); return Observable.merge(catalog, social); }).flatMap(data -> { return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER); });
  • 16. return new UserCommand(userId).observe().flatMap(user -> { Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); return Observable.merge(catalog, social); }).flatMap(data -> { return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER); });
  • 17. return new UserCommand(userId).observe().flatMap(user -> { Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); return Observable.merge(catalog, social); }).flatMap(data -> { return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER); });
  • 18. return new UserCommand(userId).observe().flatMap(user -> { Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); return Observable.merge(catalog, social); }).flatMap(data -> { return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER); });
  • 19. return new UserCommand(userId).observe().flatMap(user -> { Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); return Observable.merge(catalog, social); }).flatMap(data -> { return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER); });
  • 20. return new UserCommand(userId).observe().flatMap(user -> { Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); return Observable.merge(catalog, social); }).flatMap(data -> { return response.writeAndFlush(new ServerSentEvent("", "data", SimpleJson.mapToJson(data)), EdgeServer.SSE_TRANSFORMER); });
  • 21. +
  • 22. 1.3.x (current production) 1.4 Release Candidate (available now) - support for fully non-blocking 1.4.0 Final (coming months)
  • 23. 0.19.x (current production) 0.20 Release Candidates (coming weeks) - the “backpressure” release 0.20.0 Final 1.0 Release Candidates (Summer 2014) - no more breaking changes 1.0.0 Final (Summer/Fall 2014)
  • 24. github.com/Netflix/RxJava github.com/ReactiveX/RxJava Version 1.x to be released on Maven Central with groupId io.reactivex.*
  • 26. Along the way we started thinking about non-blocking IO ...
  • 29.
  • 30. RxNetty Performance client: wrk -t 4 -c 400 server CPUs ~2% idle NOTE: It is still early days for RxNetty tuning; more to come
  • 31. Tuning for an acceptable latency distribution client: ab server CPU usage varies with load
  • 32. RxNetty vs Tomcat Event loop model more efficient than thread pools: ● Reduces thread CPU overheads ● Reduced thread lock contention ● Better work scheduling: platform chooses, instead of the kernel scheduling threads ● Warmer CPU caches and memory locality on NUMA: event worker threads can have better CPU affinity
  • 33. RxNetty Micro Benchmarking Server: AWS c3.xlarge, tuned to reduce perturbations Client: Multi-threaded (wrk -t 4 -c 100/400), 1 min warmup ● Sufficient load to exhaust CPU capacity. Active Benchmarking Methodology: ● Tools: sysstat, perf_events, SystemTap, flame graphs, … ● USE Method, static performance tuning, etc. ● Target analyzed during benchmark confirm target results and identify (and tune) true limiters.
  • 35. Hello World ● All platforms are <100us for Hello World, so their CPU overheads are already negligible for this workload. ○ Consider application compute times of >1ms ● Hence testing “Hello Netflix” as well: a basic Netflix service Hello World with dependency requests. ● Although, Hello World max latency (not pictured) was still much higher for Tomcat...
  • 36. Visualizing Tomcat Overheads ● Flame graph of Java CPU time for Hello World benchmark ● Thread and I/O management overheads
  • 37. Visualizing RxNetty Overheads ● Flame graph of Java CPU time for Hello World ● Time in read() and write() (doing I/O; ie, doing “work”) dominates ● Flame graphs also studied of kernel and user-time ● Many improvements found and fixed
  • 38. Blog post forthcoming… Keywords: ● Oracle JDK 1.8.0 (others tried); Xmx & Xms; different GCs and settings, eg -XX:+UseConcMarkSweepGC ● Apache-tomcat 7.0.54: tested BIO, NIO, APR; maxThreads=150 or 512; maxQueueSize=up to 400; acceptCount=up to 100; disabled access log, ... ● Node.js 0.6.12 with clustering (faster than 0.10/0.11) ● vert.x 2.1 with -instances 4 ● Java profilers: Google lightweight java profiler; JFR; … ● perf_events; SystemTap; flame graphs, ...
  • 39. RxNetty & Karyon 2.0 @NiteshKant
  • 40. Netflix IPC Stack (1.0) A p a c h e H T T P C l i e n t Eureka (Service Registry) Server (Karyon) Apache Tomcat Client H y s t r i x E V C a c h e Ribbon Load Balancing Eureka Integration Metrics (Servo) Bootstrapping (Governator) Metrics (Servo) Admin ConsoleHTTP Eureka Integration Registration Fetch Registry A Blocking Architecture
  • 41. Netflix IPC Stack (2.0) Client (Ribbon 2.0) Eureka (Service Registry) Server (Karyon) Ribbon Transport Load Balancing Eureka Integration Metrics (Servo) Bootstrapping (Governator) Metrics (Servo) Admin Console HTTP Eureka Integration Registration Fetch Registry Ribbon Hystrix EVCache R x N e t t y RxNetty UDP TCP WebSockets SSE A Completely Reactive Architecture
  • 42. “We want an extremely performant IPC library” Heard this before?
  • 43. Reinventing The Wheel? Image Courtesy: Oxford Creativity Finagle Vert.x Ratpack Tons of Netty based Frameworks?
  • 44. On the lookout ….. ● Low level control. ○ Traffic Shaping. (Zuul) ○ Backpressure. ● Netflix “fit” ○ Reactive programming model. ○ Netflix Components (Eureka, Archaius, Governator, etc.)
  • 45. RxNetty Reactive Extensions To Netty Nucleus of Netflix’s IPC stack Powering Ribbon 2.0 & Karyon 2.0 https://github.com/Netflix/RxNetty
  • 46. Example (Server Sent Events) RxNetty.createHttpServer(8887, (request, response) -> { return Observable.interval(1, TimeUnit.SECONDS) .flatMap(interval -> { return response.writeAndFlush(new ServerSentEvent(...)); }); }, PipelineConfigurators.<ByteBuf>sseServerConfigurator()).start(); Server Client RxNetty.<ByteBuf, ServerSentEvent>createHttpClient("127.0.0.1", 8887, PipelineConfigurators.sseClientConfigurator()) .submit(HttpClientRequest.<ByteBuf>createGet("/")) .flatMap(response -> response.getContent()) .toBlocking().forEach(event -> System.out.println(event))
  • 47. data: interval: 0 data: interval: 1 data: interval: 2 data: interval: 3 Output …... data: interval: 4 data: interval: 5
  • 48. Example (Stream Aggregation) RxNetty.createHttpServer(8887, (request, response) -> { return Observable.interval(1, TimeUnit.SECONDS) .flatMap(interval -> { return response.writeAndFlush(new ServerSentEvent(...)); }); }, PipelineConfigurators.<ByteBuf>sseServerConfigurator()).start(); { } *3
  • 49. Example (Stream Aggregation) Observable.merge(RxNetty.<ByteBuf, ServerSentEvent>createHttpClient("127.0.0.1", 8887...), RxNetty.<ByteBuf, ServerSentEvent>createHttpClient("127.0.0.1", 8888...), RxNetty.<ByteBuf, ServerSentEvent>createHttpClient("127.0.0.1", 8889...)) ).toBlocking().forEach(event -> System.out.println(event)) RxNetty.createHttpServer(8887, ...).start(); RxNetty.createHttpServer(8888, ...).start(); RxNetty.createHttpServer(8889, ...).start();
  • 50. data: interval (8887): 0 data: interval (8888): 0 data: interval (8887): 1 data: interval (8887): 2 Output …... data: interval (8889): 0 data: interval (8888): 1
  • 51. Karyon 2.0 ● Adds Netflix constructs (governator, eureka, archaius, etc.) on RxNetty. ● Provides extensions (servlet, jersey, etc.) to RxNetty. ● More palatable to application developers.
  • 52. Example @ArchaiusBootstrap @KaryonBootstrap(name = "hello-netflix-oss") @Modules(include = {HelloNossApp.KaryonJerseyModuleImpl.class, KaryonWebAdminModule.class, KaryonEurekaModule.class}) public final class HelloNossApp { public static class KaryonJerseyModuleImpl extends KaryonJerseyModule { protected void configure() { super.configure(); bind(AuthenticationService.class).to(AuthenticationServiceImpl.class); } public int serverPort() { return 8888; } public int shutdownPort() { return 8899; } public void configureInterceptors(GovernatorHttpInterceptorSupport<ByteBuf, ByteBuf> interceptorSupport) { interceptorSupport.forUri("/hello").interceptIn(AuthInterceptor.class); } } }
  • 54. ● Tendency to become “fat” with boilerplate code ● Hystrix integration ● Go “async” ● “Declare” a client, rather than “write” a client Ribbon 2.0 - Motivation
  • 55. Ribbon 2.0: Let’s tie ‘em up
  • 56. Ribbon 2.0 - New “ribbon” module ● Template support for building HTTP request ● Rx style non-blocking and blocking APIs ● Hystrix built-in for fault tolerance ● Pluggable cache access with EVCache implementation ● Annotation based client creation as an alternative
  • 57. Ribbon 2.0 - Annotation Example public interface MovieService { RibbonRequest<Recommendations> recommendationsByUserId(@Var("userId") String userId); } @TemplateName(“recommendations”) @Http(method = HttpMethod.GET, uriTemplate="/users/{userId}/recommendations") @Hystrix(fallbackHandler = RecommendationFallbackHandler.class) @EvCache(name = "movie-rec", appName = "movieService", cacheKeyTemplate = "{userId}") MovieService movieService = Ribbon.from(MovieService.class); Observable<Recommendations> result = movieService.recommendationsByUserId(“user1”) .toObservable();
  • 58. Ribbon 2: Template Example HttpResourceGroup movieService = Ribbon.createHttpResourceGroup("movieService"); HttpRequestTemplate<ByteBuf> template1 = movieService.newRequestTemplate("recommendationsByUserId", ByteBuf.class) .withMethod("GET") .withUriTemplate("/users/{userId}/recommendations") .withFallbackProvider(new RecommendationServiceFallbackHandler()); RibbonRequest<ByteBuf> request = template1.requestBuilder() .withRequestProperty("userId", “user1”).build(); Observable<ByteBuf> result = request.toObservable(); // non blocking ByteBuf result = request.execute(); // blocking
  • 59. Ribbon 2.0 - Other New Features ● Ribbon’s async module - “ribbon-transport” ○ HTTP, TCP and UDP clients on top of RxNetty with load balancing capability ● New load balancing features ○ Command pattern load balancing APIs implemented with Rx for easy integration for third party client ○ Shuffle sharding server list for fault isolation
  • 62. Retrofit Example: GitHub API List Contributors GET /repos/:owner/:repo/contributors
  • 63. Retrofit GET /repos/:owner/:repo/contributors interface GitHub { List<Contributor> contributors( String owner, String repo); } class Contributor { String login; long contributions; }
  • 64. Retrofit GET /repos/:owner/:repo/contributors interface GitHub { @GET("/repos/{owner}/{repo}/contributors") List<Contributor> contributors( String owner, String repo); }
  • 65. Retrofit GET /repos/:owner/:repo/contributors interface GitHub { @GET("/repos/{owner}/{repo}/contributors") List<Contributor> contributors( @Path("owner") String owner, @Path("repo") String repo); }
  • 66. Retrofit RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://api.github.com/") .build(); GitHub gitHub = restAdapter.create(GitHub.class); List<Contributor> contributors = gitHub.contributors("netflix", "rxjava");
  • 67. Retrofit List<Contributor> contributors = gitHub.contributors("netflix", "rxjava"); for (Contributor c : contributors) { println(c.login + 't' + c.contributions); } 1483 benjchristensen 225 zsxwing 167 samuelgruetter 146 jmhofer 137 akarnokd 105 DavidMGross 102 AppliedDuality ...
  • 68. Retrofit RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://drive.google.com/api/") .setConverter(new ProtoConverter()) .build();
  • 69. Retrofit interface GitHub { @GET("/repos/{owner}/{repo}/contributors") List<Contributor> contributors( @Path("owner") String owner, @Path("repo") String repo); }
  • 70. Retrofit interface GitHub { @GET("/repos/{owner}/{repo}/contributors?anon=true") List<Contributor> contributors( @Path("owner") String owner, @Path("repo") String repo); }
  • 71. Retrofit interface GitHub { @GET("/repos/{owner}/{repo}/contributors") List<Contributor> contributors( @Path("owner") String owner, @Path("repo") String repo, @Query("anon") boolean includeAnonymous); }
  • 72. Retrofit interface GitHub { @POST("/repos/{owner}/{repo}/hooks") Response createHook( @Path("owner") String owner, @Path("repo") String repo, @Body Hook hook); } class Hook { String name; Map<String, Object> config; List<String> events; boolean active; }
  • 73. Retrofit RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://drive.google.com/api/") .setConverter(new ProtoConverter()) .setClient(new OkClient()) .build();
  • 74. Retrofit OkHttpClient client = new OkHttpClient(); client.setProtocols(Arrays.asList(HTTP_2)); RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://drive.google.com/api/") .setConverter(new ProtoConverter()) .setClient(new OkClient(client)) .build();
  • 75. Retrofit ● Form URL encoding ● Response streaming ● Request interceptors ● Dynamic headers ● Android ● Multipart ● Logging ● Mock RestAdapter ● Asynchronous invoke ● AppEngine ...and more!
  • 76. Retrofit + RxJava interface GitHub { @GET("/repos/{owner}/{repo}/contributors") List<Contributor> contributors( @Path("owner") String owner, @Path("repo") String repo); }
  • 77. Retrofit + RxJava interface GitHub { @GET("/repos/{owner}/{repo}/contributors") Observable<List<Contributor>> contributors( @Path("owner") String owner, @Path("repo") String repo); }
  • 78. Retrofit + RxJava gitHub.contributors("netflix", "rxjava") .lift(flattenList()) .forEach(c -> println(c.login + 't' + c.contributions)); 1483 benjchristensen 225 zsxwing 167 samuelgruetter 146 jmhofer 137 akarnokd 105 DavidMGross 102 AppliedDuality ...
  • 79. Retrofit + RxJava interface GitHub { @GET("/repos/{owner}/{repo}/contributors") Observable<List<Contributor>> contributors( @Path("owner") String owner, @Path("repo") String repo); @GET("/users/{user}") Observable<User> user( @Path("user") String user); }
  • 80. Retrofit + RxJava gitHub.contributors("netflix", "rxjava") .lift(flattenList()) .flatMap(c -> gitHub.user(c.login)) .forEach(user -> println(user.name)); Ben Christensen Shixiong Zhu null Joachim Hofer null David Gross null ...
  • 81. Retrofit + RxJava gitHub.contributors("netflix", "rxjava") .lift(flattenList()) .flatMap(c -> gitHub.user(c.login)) .filter(user -> user.name != null) .forEach(user -> println(user.name)); Ben Christensen Shixiong Zhu Joachim Hofer David Gross Matthias Käppler Justin Ryan Mairbek Khadikov ...
  • 82. Retrofit + RxJava interface GitHub { @GET("/repos/{owner}/{repo}/contributors") Observable<List<Contributor>> contributors( @Path("owner") String owner, @Path("repo") String repo); @GET("/users/{user}/starred") Observable<List<Repo>> starred( @Path("user") String user); }
  • 83. Retrofit + RxJava gitHub.contributors("netflix", "rxjava") .lift(flattenList()) .flatMap(c -> gitHub.starred(c.login)) .lift(flattenList()) .groupBy(r -> r.full_name) .flatMap(g -> g.count().map(c -> c + "t" + g.getKey())) .toSortedList((a, b) -> b.compareTo(a)) .lift(flattenList()) .take(8) .forEach(Main::println);
  • 84. Retrofit + RxJava 7 Netflix/RxJava 2 twitter/finagle 2 scala/scala 2 mbostock/d3 2 kpelykh/docker-java 2 Netflix/zuul 2 Netflix/feign 2 Netflix/archaius
  • 85. Retrofit + RxJava gitHub.contributors("square", "retrofit") .lift(flattenList()) .flatMap(c -> gitHub.starred(c.login)) .lift(flattenList()) .groupBy(r -> r.full_name) .flatMap(g -> g.count().map(c -> c + "t" + g.getKey())) .toSortedList((a, b) -> b.compareTo(a)) .lift(flattenList()) .take(8) .forEach(Main::println);
  • 86. gitHub.contributors("square", "retrofit") .lift(flattenList()) .flatMap(c -> gitHub.starred(c.login)) .lift(flattenList()) .filter(r -> !r.full_name.startsWith("square/")) .groupBy(r -> r.full_name) .flatMap(g -> g.count().map(c -> c + "t" + g.getKey())) .toSortedList((a, b) -> b.compareTo(a)) .lift(flattenList()) .take(8) .forEach(Main::println); Retrofit + RxJava
  • 87. Retrofit + RxJava 4 frankiesardo/auto-parcel 4 Comcast/FreeFlow 3 xxv/android-lifecycle 3 robolectric/robolectric 3 inmite/android-butterknife-zelezny 3 google/auto 3 facebook/rebound 3 etsy/AndroidStaggeredGrid 3 Netflix/RxJava
  • 90. Couchbase is... Document-oriented (JSON) database ... Low latency & high throughput … Highly available and scalable ...
  • 91. Motivations with Couchbase Java ➢ Simplify ... ➢ Even *more* performance ➢ Build for the JVM, not for the Java language ○ Have Scala, JRuby already being worked on
  • 92. History of Concurrency Core Java component, spymemcached, has used Futures since 2006 or so. ➢ Always been ahead of most other database like clients, however… ➢ Difficult for developers to code against ○ Dumb benchmarks turn into FAQs
  • 93. while (true) { client.set("foo", "bar") };
  • 94. while (true) { client.set("foo", "bar") }; Signature: public OperationFuture<java.lang.Boolean> set(java.lang.String key, java.lang.Object value);
  • 95. while (true) { client.set("foo", "bar").get() };
  • 96. What we’re Building On ➢ A set of new components ○ RxJava (both internal and public interface) ○ Netty (internal only) ○ LMAX Disruptor
  • 97. RxJava for Couchbase ➢ Will be part of the client’s public API ○ Helps us support Java 8, but is also backward compatible ■ Generally get a great Java 8 experience for free! ➢ Also using RxJava extensively internally ○ Breaking the project into core and language façade helps build toward Scala and others
  • 98. Getting Referenced Elements client.asyncGet("posts::1").addListener(future -> { if (future.isDone() && !future.isCancelled()) { String content = (String) future.get(); List<String> ids = comments_ids_from_json(content); int i = 0; for (String id : ids) { if (i++ == 5) { break; } client.asyncGet(id).addListener(future1 -> { if (future1.isDone() && !future1.isCancelled()) { System.out.println(future1.get()); } }); } } });
  • 99. Getting Referenced Elements Rx Way bucket .get("posts::1") .map(document -> document.content().getArray("comments")) .flatMap(comments -> Observable.from(comments.toList())) .take(5) .filter(o -> o instanceof String) .flatMap(o -> bucket.get((String) o)) .subscribe(doc -> System.out.println(doc.content()));
  • 100. Beauty of Error Handling return super.registerBucket(name, password).flatMap(new Func1<Boolean, Observable<BucketStreamingResponse>>() { @Override public Observable<BucketStreamingResponse> call(Boolean aBoolean) { return cluster().send(new BucketStreamingRequest(TERSE_PATH, name, password)); } }).onErrorResumeNext(new Func1<Throwable, Observable<BucketStreamingResponse>>() { @Override public Observable<BucketStreamingResponse> call(Throwable throwable) { return cluster().send(new BucketStreamingRequest(VERBOSE_PATH, name, password)); } })
  • 101. Couchbase React to our Dev Preview 2! Michael Nitschinger’s blog: http://blog.couchbase.com/couchbase-java-sdk-200-developer-preview-2
  • 102. Five Minutes of Futures Will Sargent, Typesafe
  • 103. Reactive Interface In Theory Looks like: ● Responsive? ● Scalable? ● Resilient? ● Event-Driven?
  • 104. Reactive Interface in Practice Really looks like this: trait FooService { def find(fooId:FooID) : Future[Option[Foo]] }
  • 105. Plain English “Non-blocking” / “Async” means either Future[T] or Actor model
  • 106. Choices To Akka, or Not to Akka?
  • 107. Akka with Futures Akka to Future: val myFuture = actorRef ? message Future to Akka: futureStuff pipeTo actorRef
  • 108. Assuming a Services based API val fooFuture = fooService.get(1) val barFuture = barService.get(2) val quuxFuture = quuxService.get(3) ...Simple, right?
  • 109. Not so fast val fooFuture = fooService.get(1) val barFuture = barService.get(foo.barId) val quuxFuture = quuxService.get(bar.quuxId) ...wat.
  • 110. FLATMAP THAT fooService.get(1).map { maybeFoo => maybeFoo.flatMap { foo => val barFuture = barService.get(foo.barId) // do the same for bar & quux } }
  • 111. For comprehensions! for { maybeFoo <- fooService.get(1) } yield { for { // Option / Future does not compose foo <- maybeFoo } yield ... }
  • 112. Scala Async! async { val maybeFoo = await(fooService.get(1)) maybeFoo.flatMap { foo => val bar = await(barService.get(2)) } }
  • 113. Scala Async Sadness COMPILE ERROR. “await must not be used inside a closure nested within an async block” == no flatMap of that.
  • 114. Monads don’t compose But before reaching for readers/transformers: ● Use small methods ● Short circuit ● Use loan patterns
  • 115. Use Small Methods def foo2bar(ff:Future[Foo]) : Future[Bar]
  • 116. Short Circuit implicit def flatten[A](fofoa: Future[Option [Future[Option[A]]]]): Future[Option[A]] = fofoa. flatMap(_.getOrElse(Future.successful(None)))
  • 117. Loan Pattern def getFuture[T](futureOptionBlock: Future[Option[T]])(foundBlock: (T => Future[Result])): Future[Result] = { futureOptionBlock.flatMap { case Some(found) => foundBlock(found) case None => Future.successful(NotFound) } }
  • 118. What’s next? Demos, food and drinks! August 20th - NetflixOSS and Cloud Security