SlideShare una empresa de Scribd logo
1 de 180
Evolution of the Netflix API
QCon San Francisco - November 2013
Ben Christensen

Software Engineer – Edge & Playback Services at Netflix
@benjchristensen
!
!
!
!
http://techblog.netflix.com/
Watch the video with slide
synchronization on InfoQ.com!
http://www.infoq.com/presentations
/netflix-api-evolution

InfoQ.com: News & Community Site
• 750,000 unique visitors/month
• Published in 4 languages (English, Chinese, Japanese and Brazilian
Portuguese)
• Post content from our QCon conferences
• News 15-20 / week
• Articles 3-4 / week
• Presentations (videos) 12-15 / week
• Interviews 2-3 / week
• Books 1 / month
Presented at QCon San Francisco
www.qconsf.com
Purpose of QCon
- to empower software development by facilitating the spread of
knowledge and innovation
Strategy
- practitioner-driven conference designed for YOU: influencers of
change and innovation in your teams
- speakers and topics driving the evolution and innovation
- connecting and catalyzing the influencers and innovators
Highlights
- attended by more than 12,000 delegates since 2007
- held in 9 cities worldwide
Evolution of the Netflix API
More than 40 million Subscribers
in 50+ Countries and Territories
Netflix accounts for 33% of Peak Downstream
Internet Traffic in North America

Netflix subscribers are watching
more than 1 billion hours a month
API traffic has grown from
~20 million/day in 2010 to >2 billion/day
millions of API requests per day

2000

1500

1000

500

0
2010

2011

2012

Today
Discovery

Streaming
Netflix API

Streaming
Evolution of the Netflix API
At the start …

millions of API requests per day

2000

1500

1000

500

0
2008

2009

2010

2011

2012

Today
2008 API Launch
Targeted 100% at External Developers
Open API

Netflix Devices
2008 API Launch
Targeted 100% at External Developers

Purpose
A “Thousand Flowers” of
3rd party innovation
!

Audience
External Developers
Pre-Cloud Architecture
API

Service

Service

Service

Oracle

Service
In 2011 …

millions of API requests per day

2000

1500

1000

500

0
2008

2009

2010

2011

2012

Today
99.9% Netflix Devices
Open API

Netflix Devices
Targeted at Internal Developers
Open API

Netflix Devices
Targeted at Internal Developers

Purpose
Enable Netflix Experience
!

Audience
Netflix Device and UI Teams
Scale & Resilience
!

Performance & Innovation
Scale & Resilience
!

Performance & Innovation
Netflix API

Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J

Dependency M

Dependency P

Dependency I

Dependency K

Dependency N

Dependency Q

Dependency L

Dependency O

Dependency R
Netflix API

Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J

Dependency M

Dependency P

Dependency I

Dependency K

Dependency N

Dependency Q

Dependency L

Dependency O

Dependency R
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
AWS
Availability Zone

AWS
Availability Zone

AWS
Availability Zone
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
User Request

Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J
Dependency M

Dependency P

Dependency I

Dependency K
Dependency N

Dependency Q

Dependency L
Dependency O

Dependency R
User Request

Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J
Dependency M

Dependency P

Dependency I

Dependency K
Dependency N

Dependency Q

Dependency L
Dependency O

Dependency R

User request
blocked by
latency in
single
network call
Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J

Dependency M
Dependency P

Dependency I

Dependency K

Dependency N
Dependency Q

Dependency L

Dependency O
Dependency R

User Request

User Request

User Request

User Request

User Request

User Request

User Request

.............................................

At high
volume
all request
threads can
block in
seconds
!

Dozens of dependencies.
!

One going bad takes everything down.
!

30
99.99%

= 99.7% uptime
!

0.3% of 1 billion = 3,000,000 failures
!

2+ hours downtime/month
!
!
!

Reality is generally worse.
CONSTRAINTS

Speed of Iteration
!

Client Libraries
!

Mixed Environment
CONSTRAINTS

Speed of Iteration
!

Client Libraries
!

Mixed Environment
CONSTRAINTS

Speed of Iteration
!

Client Libraries
!

Mixed Environment
CONSTRAINTS

Speed of Iteration
!

Client Libraries
!

Mixed Environment
Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J

Dependency M
Dependency P

Dependency I

Dependency K

Dependency N
Dependency Q

Dependency L

Dependency O
Dependency R

User Request

User Request

User Request

User Request

User Request

User Request

User Request

.............................................
User Request

User Request

User Request

Logic - argument validation, caches, metrics, logging,
multivariate testing, routing, etc
Serialization - URL and/or body generation

Network Request - TCP/HTTP, latency, 4xx, 5xx, etc

.............................................
Deserialization - JSON/XML/Thrift/Protobuf/etc

Dependency B

cy D

Dependency C

Dependency E

dency G

ependency J
Dependency M

Logic - validation, decoration, object model, caching,
metrics, logging, etc

Dependency F

Dependency H
Dependency K
Dependency N

Dependency I
Dependency L
Dependency O
> 80% of requests rejected

Median
Latency
[Sat Jun 30 04:01:37 2012] [error] proxy: HTTP: disabled connection for (127.0.0.1)

"Timeout guard" daemon prio=10 tid=0x00002aaacd5e5000 nid=0x3aac runnable [0x00002aaac388f000] java.lang.Thread.State: RUNNABLE!
at java.net.PlainSocketImpl.socketConnect(Native Method)!
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)!
- locked <0x000000055c7e8bd8> (a java.net.SocksSocketImpl)!
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)!
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)!
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)!
at java.net.Socket.connect(Socket.java:579)!
at java.net.Socket.connect(Socket.java:528)!
at java.net.Socket.(Socket.java:425)!
at java.net.Socket.(Socket.java:280)!
at org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory.createSocket(DefaultProtocolSocketFactory.java:80)!
at org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory$1.doit(ControllerThreadSocketFactory.java:91)!
at org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory$SocketTask.run(ControllerThreadSocketFactory.java:158) at java.lang.Thread.run(Thread.java:722)
User Request

Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J
Dependency M

Dependency P

Dependency I

Dependency K
Dependency N

Dependency Q

Dependency L
Dependency O

Dependency R
User Request

Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J
Dependency M

Dependency P

Dependency I

Dependency K
Dependency N

Dependency Q

Dependency L
Dependency O

Dependency R
User Request

Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J
Dependency M

Dependency P

Dependency I

Dependency K
Dependency N

Dependency Q

Dependency L
Dependency O

Dependency R
User Request

Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J
Dependency M

Dependency P

Dependency I

Dependency K
Dependency N

Dependency Q

Dependency L
Dependency O

Dependency R
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
circle color and size represent
health and traffic volume
circle color and size represent
health and traffic volume

2 minutes of request rate to
show relative changes in traffic
circle color and size represent
health and traffic volume

2 minutes of request rate to
show relative changes in traffic
hosts reporting from cluster
circle color and size represent
health and traffic volume

2 minutes of request rate to
show relative changes in traffic
hosts reporting from cluster

last minute latency percentiles
circle color and size represent
health and traffic volume

2 minutes of request rate to
show relative changes in traffic
hosts reporting from cluster

Circuit-breaker
status
last minute latency percentiles
circle color and size represent
health and traffic volume
Request rate
2 minutes of request rate to
show relative changes in traffic
hosts reporting from cluster

Circuit-breaker
status
last minute latency percentiles
circle color and size represent
health and traffic volume

Error percentage of
last 10 seconds
Request rate

2 minutes of request rate to
show relative changes in traffic
hosts reporting from cluster

Circuit-breaker
status
last minute latency percentiles
Error percentage of
last 10 seconds

circle color and size represent
health and traffic volume

Request rate
2 minutes of request rate to
show relative changes in traffic

Circuit-breaker
status

hosts reporting from cluster

last minute latency percentiles
Rolling 10 second counters
with 1 second granularity

Successes
Short-circuited (rejected)

Thread timeouts
Thread-pool Rejections
Failures/Exceptions
User Request

Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J
Dependency M

Dependency P

Dependency I

Dependency K
Dependency N

Dependency Q

Dependency L
Dependency O

Dependency R
Evolution of the Netflix API
Zuul Routing Layer

Canary vs Baseline
Squeeze

"Coalmine"

Production
Zuul Routing Layer

Canary vs Baseline
Squeeze

"Coalmine"

Production
Zuul Routing Layer

Canary vs Baseline
Squeeze

"Coalmine"

Production
Zuul Routing Layer

Canary vs Baseline
Squeeze

"Coalmine"

Production
Zuul Routing Layer

Canary vs Baseline
Squeeze

"Coalmine"

Production
User Request

Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J
Dependency M

Dependency P

Dependency I

Dependency K
Dependency N

Dependency Q

Dependency L
Dependency O

Dependency R

System
Relationship
Over
Network
without
Bulkhead
Zuul Routing Layer

Canary vs Baseline
Squeeze

"Coalmine"

Production
Zuul Routing Layer

Canary vs Baseline
Squeeze

"Coalmine"

Production
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Predictive + Reactive Auto-Scaling
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Scale & Resilience
!

Performance & Innovation
Netflix API

Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J

Dependency M

Dependency P

Dependency I

Dependency K

Dependency N

Dependency Q

Dependency L

Dependency O

Dependency R
Netflix API

Dependency A

Dependency B

Dependency D

Dependency C

Dependency E

Dependency G

Dependency F

Dependency H

Dependency J

Dependency M

Dependency P

Dependency I

Dependency K

Dependency N

Dependency Q

Dependency L

Dependency O

Dependency R
One Size Fits All RESTful API

millions of API requests per day

2000

1500

1000

500

0
2010

2011

2012

Today
One Size Fits All RESTful API

millions of API requests per day

2000

1500

1000

500

0
2010

2011

2012

Today
One Size Fits All RESTful API
1000+ Devices
millions of API requests per day

2000

1500

1000

500

0
2010

2011

2012

Today
We wanted to re-architecture our call patterns ...
... to collapse network traffic into coarse API calls ...

nested, conditional, concurrent execution
... and we wanted to allow
anybody to create
endpoints, not just the
“API Team”
Evolution of the Netflix API
Concurrency without each engineer
reading and re-reading this →
!

(awesome book ... everybody isn’t going to - or
should have to - read it though, that’s the point)
Owner of api should retain control
of concurrency behavior.
Owner of api should retain control
of concurrency behavior.
public	
  Data	
  getData();
What if the implementation needs to change
from synchronous to asynchronous?
!

How should the client execute that method
without blocking? spawn a thread?
public	
  Data	
  getData();
public	
  void	
  getData(Callback<T>	
  c);	
  
!

public	
  Future<T>	
  getData();	
  
!

public	
  Future<List<Future<T>>>	
  getData();	
  
!
!

other options ... ?
Reactive Programming with Rx
Iterable
pull
T next()
throws Exception
returns;

Observable
push
onNext(T)
onError(Exception)
onCompleted()
(Functional) Reactive Programming with RxJava
Iterable
pull
T next()
throws Exception
returns;

Observable
push
onNext(T)
onError(Exception)
onCompleted()
(Functional) Reactive Programming with RxJava
Iterable
pull
T next()
throws Exception
returns;

Observable
push
onNext(T)
onError(Exception)
onCompleted()
(Functional) Reactive Programming with RxJava
Iterable
pull
T next()
throws Exception
returns;

Observable
push
onNext(T)
onError(Exception)
onCompleted()
Iterable
pull
T next()
throws Exception
returns;
!
	
  //	
  Iterable<String>	
  	
  
	
  //	
  that	
  contains	
  75	
  Strings	
  
	
  getDataFromLocalMemory()	
  
	
  	
  .skip(10)	
  
	
  	
  .take(5)	
  
	
  	
  .map({	
  s	
  -­‐>	
  	
  
	
  	
  	
  return	
  s	
  +	
  "_transformed"})	
  
	
  	
  .forEach(	
  
	
  	
  	
  	
  	
  {	
  println	
  "next	
  =>	
  "	
  +	
  it})	
  

Observable
push
onNext(T)
onError(Exception)
onCompleted()
!
	
  //	
  Observable<String>	
  	
  
	
  //	
  that	
  emits	
  75	
  Strings	
  
	
  getDataFromNetwork()	
  
	
  	
  .skip(10)	
  
	
  	
  .take(5)	
  
	
  	
  .map({	
  s	
  -­‐>	
  	
  
	
  	
  	
  return	
  s	
  +	
  "_transformed"})	
  
	
  	
  .subscribe(	
  
	
  	
  	
  	
  	
  {	
  println	
  "onNext	
  =>	
  "	
  +	
  it})	
  
Iterable
pull
T next()
throws Exception
returns;
!
	
  //	
  Iterable<String>	
  	
  
	
  //	
  that	
  contains	
  75	
  Strings	
  
	
  getDataFromLocalMemory()	
  
	
  	
  .skip(10)	
  
	
  	
  .take(5)	
  
	
  	
  .map({	
  s	
  -­‐>	
  	
  
	
  	
  	
  return	
  s	
  +	
  "_transformed"})	
  
	
  	
  .forEach(	
  
	
  	
  	
  	
  	
  {	
  println	
  "onNext	
  =>	
  "	
  +	
  it})	
  

Observable
push
onNext(T)
onError(Exception)
onCompleted()
!
	
  //	
  Observable<String>	
  	
  
	
  //	
  that	
  emits	
  75	
  Strings	
  
	
  getDataFromNetwork()	
  
	
  	
  .skip(10)	
  
	
  	
  .take(5)	
  
	
  	
  .map({	
  s	
  -­‐>	
  	
  
	
  	
  	
  return	
  s	
  +	
  "_transformed"})	
  
	
  	
  .subscribe(	
  
	
  	
  	
  	
  	
  {	
  println	
  "onNext	
  =>	
  "	
  +	
  it})	
  
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

String s = getData(args);	
if (s.equals(x)) {	
// do something	
} else {	
// do something else	
}
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

Iterable<String> values = getData(args);	
for (String s : values) {	
if (s.equals(x)) {	
// do something	
} else {	
// do something else	
}	
}
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

Future<String> s = getData(args);	
if (s.get().equals(x)) {	
// do something	
} else {	
// do something else	
}
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

Future<String> s = getData(args);	
if (s.get().equals(x)) {	
// do something	
} else {	
// do something else	
}
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

Future<String> s = getData(args);	
Futures.addCallback(s, 	
new FutureCallback<String> {	
public void onSuccess(String s) {	
if (s.equals(x)) {	
// do something	
} else {	
// do something else	
}	
}	
	
}, executor);
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

Future<String> s = getData(args);	
Futures.addCallback(s, 	
new FutureCallback<String> {	
public void onSuccess(String s) {	
if (s.equals(x)) {	
// do something	
} else {	
// do something else	
}	
}	
	
}, executor);
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

Future<String> s = getData(args);	
Futures.addCallback(s, 	
new FutureCallback<String> {	
public void onSuccess(String s) {	
if (s.equals(x)) {	
// do something	
} else {	
// do something else	
}	
}	
	
}, executor);
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

CompletableFuture<String> s = getData(args);	
s.thenApply((v) -> {	
if (v.equals(x)) {	
// do something	
} else {	
// do something else	
}	
});
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

CompletableFuture<String> s = getData(args);	
s.thenApply((v) -> {	
if (v.equals(x)) {	
// do something	
} else {	
// do something else	
}	
});
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

Future<String> s = getData(args);	
s.map({ s -> 	
if (s.equals(x)) {	
// do something	
} else {	
// do something else	
}	
});
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

Future<String> s = getData(args);	
s.map({ s -> 	
if (s.equals(x)) {	
// do something	
} else {	
// do something else	
}	
});
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

Future<String> s = getData(args);	
s.map({ s -> 	
if (s.equals(x)) {	
// do something	
} else {	
// do something else	
}	
});
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

Observable<String> s = getData(args);	
s.map({ s -> 	
if (s.equals(x)) {	
// do something	
} else {	
// do something else	
}	
});
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

Observable<String> s = getData(args);	
s.map({ s -> 	
if (s.equals(x)) {	
// do something	
} else {	
// do something else	
}	
});
Single

Multiple

Sync

T getData()

Iterable<T> getData()

Async

Future<T> getData()

Observable<T> getData()

Observable<String> s = getData(args);	
s.map({ s -> 	
if (s.equals(x)) {	
// do something	
} else {	
// do something else	
}	
});
instead of a blocking api ...
class	
  VideoService	
  {	
  
	
  	
  	
  def	
  VideoList	
  getPersonalizedListOfMovies(userId);	
  
	
  	
  	
  def	
  VideoBookmark	
  getBookmark(userId,	
  videoId);	
  
	
  	
  	
  def	
  VideoRating	
  getRating(userId,	
  videoId);	
  
	
  	
  	
  def	
  VideoMetadata	
  getMetadata(videoId);	
  
}

... create an observable api:
class	
  VideoService	
  {	
  
	
  	
  	
  def	
  Observable<VideoList>	
  getPersonalizedListOfMovies(userId);	
  
	
  	
  	
  def	
  Observable<VideoBookmark>	
  getBookmark(userId,	
  videoId);	
  
	
  	
  	
  def	
  Observable<VideoRating>	
  getRating(userId,	
  videoId);	
  
	
  	
  	
  def	
  Observable<VideoMetadata>	
  getMetadata(videoId);	
  
}
RxJava
http://github.com/Netflix/RxJava

“a library for composing
asynchronous and event-based
programs using observable
sequences for the Java VM”
A Java port of Rx (Reactive Extensions)
https://rx.codeplex.com (.Net and Javascript by Microsoft)
client code treats all interactions
with the api as asynchronous
!
!

the api implementation chooses
whether something is
blocking or non-blocking
and
what resources it uses
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Netflix API

Server

Device

Optimize for Each Device. Leverage the Server
Code
SDK for API Web Service Development
SDK for API Web Service Development
SDK for API Web Service Development
api.servletResponse.writer.print("Hello")
api.servletResponse.writer.print("Hello")

$runScript.py -e PROD sample.groovy
Hello
################################################################################################
####### Script Logger (enabled via debug=true request parameter)
################################################################################################
[0ms] INFO: User => NULL
################################################################################################
####### Script Logger (enabled via debug=true request parameter)
################################################################################################
api.servletResponse.writer.print("Hello")

$runScript.py -e PROD sample.groovy
Hello
################################################################################################
####### Script Logger (enabled via debug=true request parameter)
################################################################################################
[0ms] INFO: User => NULL
################################################################################################
####### Script Logger (enabled via debug=true request parameter)
################################################################################################
api.servletResponse.writer.print("Hello")

$runScript.py -e PROD sample.groovy
Hello
################################################################################################
####### Script Logger (enabled via debug=true request parameter)
################################################################################################
[0ms] INFO: User => NULL
################################################################################################
####### Script Logger (enabled via debug=true request parameter)
################################################################################################
api.servletResponse.writer.print("Hello")

$runScript.py -e PROD sample.groovy
Hello
################################################################################################
####### Script Logger (enabled via debug=true request parameter)
################################################################################################
[0ms] INFO: User => NULL
################################################################################################
####### Script Logger (enabled via debug=true request parameter)
################################################################################################
api.servletResponse.writer.print("Hello")

$runScript.py -e PROD sample.groovy
Hello
################################################################################################
####### Script Logger (enabled via debug=true request parameter)
################################################################################################
[0ms] INFO: User => NULL
################################################################################################
####### Script Logger (enabled via debug=true request parameter)
################################################################################################
api.servletResponse.writer.print("Hello")

$runScript.py -e PROD sample.groovy
Hello
################################################################################################
####### Script Logger (enabled via debug=true request parameter)
################################################################################################
[0ms] INFO: User => NULL
################################################################################################
####### Script Logger (enabled via debug=true request parameter)
################################################################################################
public class HelloEndpoint extends APIEndpoint {	
@Override	
public void execute(APIRequest api) throws Throwable {	
// get a request parameter from servlet request	
String alias = api.servletRequest.getParameter("name");	

!
// set content type and write something to servlet response	
api.servletResponse.setContentType("application/json");	
api.servletResponse.writer.print(	
JsonUtility.toJson(	
[ alias : alias, name : api.user.firstName ]	
)	
)	

!
}	
}
public class HelloEndpoint extends APIEndpoint {	
@Override	
public void execute(APIRequest api) throws Throwable {	
// get a request parameter from servlet request	
String alias = api.servletRequest.getParameter("name");	

!
// set content type and write something to servlet response	
api.servletResponse.setContentType("application/json");	
api.servletResponse.writer.print(	
JsonUtility.toJson(	
[ alias : alias, name : api.user.firstName ]	
)	
)	

!
}	
}

runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy
public class HelloEndpoint extends APIEndpoint {	
@Override	
public void execute(APIRequest api) throws Throwable {	
// get a request parameter from servlet request	
String alias = api.servletRequest.getParameter("name");	

!
// set content type and write something to servlet response	
api.servletResponse.setContentType("application/json");	
api.servletResponse.writer.print(	
JsonUtility.toJson(	
[ alias : alias, name : api.user.firstName ]	
)	
)	

!
}	
}
runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy

{"alias":"bob","name":"Old"}
public class HelloEndpoint extends APIEndpoint {	
@Override	
public void execute(APIRequest api) throws Throwable {	
// get a request parameter from servlet request	
String alias = api.servletRequest.getParameter("name");	

!
// set content type and write something to servlet response	
api.servletResponse.setContentType("application/json");	
api.servletResponse.writer.print(	
JsonUtility.toJson(	
[ alias : alias, name : api.user.firstName ]	
)	
)	

!
}	
}
runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy

{"alias":"bob","name":"Old"}
public class HelloEndpoint extends APIEndpoint {	
@Override	
public void execute(APIRequest api) throws Throwable {	
// get a request parameter from servlet request	
String alias = api.servletRequest.getParameter("name");	

!
// set content type and write something to servlet response	
api.servletResponse.setContentType("application/json");	
api.servletResponse.writer.print(	
JsonUtility.toJson(	
[ alias : alias, name : api.user.firstName ]	
)	
)	

!
}	
}
runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy

{"alias":"bob","name":"Old"}
public class HelloEndpoint extends APIEndpoint {	
@Override	
public void execute(APIRequest api) throws Throwable {	
// get a request parameter from servlet request	
String alias = api.servletRequest.getParameter("name");	

!
// set content type and write something to servlet response	
api.servletResponse.setContentType("application/json");	
api.servletResponse.writer.print(	
JsonUtility.toJson(	
[ alias : alias, name : api.user.firstName ]	
)	
)	

!
}	
}
runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy

{"alias":"bob","name":"Old"}
public class HelloEndpoint extends APIEndpoint {	
@Override	
public void execute(APIRequest api) throws Throwable {	
// get a request parameter from servlet request	
String alias = api.servletRequest.getParameter("name");	

!
// set content type and write something to servlet response	
api.servletResponse.setContentType("application/json");	
api.servletResponse.writer.print(	
JsonUtility.toJson(	
[ alias : alias, name : api.user.firstName ]	
)	
)	

!
}	
}
runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy

{"alias":"bob","name":"Old"}
public class HelloEndpoint extends APIEndpoint {	
@Override	
public void execute(APIRequest api) throws Throwable {	
// get a request parameter from servlet request	
String alias = api.servletRequest.getParameter("name");	

!
// set content type and write something to servlet response	
api.servletResponse.setContentType("application/json");	
api.servletResponse.writer.print(	
JsonUtility.toJson(	
[ alias : alias, name : api.user.firstName ]	
)	
)	

!
}	
}
runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy

{"alias":"bob","name":"Old"}
public Observable getVideoSummary(APIVideo video) {	
// get id, title	
def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)]	

!
// get bookmark	
def bookmarkObservable = getBookmark(video)	

!
// get artwork	
def artworkObservable = getArtworkImageUrl(video)	

!
// merge them and accumulate into the seed.	
return Observable.merge(bookmarkObservable, artworkObservable)	
.reduce(seed, { aggregate, current -> aggregate << current})	
.map({ [ (video.id.toString()) : it]})	
}
public Observable getVideoSummary(APIVideo video) {	
// get id, title	
def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)]	

!
// get bookmark	
def bookmarkObservable = getBookmark(video)	

!
// get artwork	
def artworkObservable = getArtworkImageUrl(video)	

!
// merge them and accumulate into the seed.	
return Observable.merge(bookmarkObservable, artworkObservable)	
.reduce(seed, { aggregate, current -> aggregate << current})	
.map({ [ (video.id.toString()) : it]})	
}
public Observable getVideoSummary(APIVideo video) {	
// get id, title	
def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)]	

!
// get bookmark	
def bookmarkObservable = getBookmark(video)	

!
// get artwork	
def artworkObservable = getArtworkImageUrl(video)	

!
// merge them and accumulate into the seed.	
return Observable.merge(bookmarkObservable, artworkObservable)	
.reduce(seed, { aggregate, current -> aggregate << current})	
.map({ [ (video.id.toString()) : it]})	
}
public Observable getVideoSummary(APIVideo video) {	
// get id, title	
def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)]	

!
// get bookmark	
def bookmarkObservable = getBookmark(video)	

!
// get artwork	
def artworkObservable = getArtworkImageUrl(video)	

!
// merge them and accumulate into the seed.	
return Observable.merge(bookmarkObservable, artworkObservable)	
.reduce(seed, { aggregate, current -> aggregate << current})	
.map({ [ (video.id.toString()) : it]})	
}
public Observable getVideoSummary(APIVideo video) {	
// get id, title	
def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)]	

!
// get bookmark	
def bookmarkObservable = getBookmark(video)	

!
// get artwork	
def artworkObservable = getArtworkImageUrl(video)	

!
// merge them and accumulate into the seed.	
return Observable.merge(bookmarkObservable, artworkObservable)	
.reduce(seed, { aggregate, current -> aggregate << current})	
.map({ [ (video.id.toString()) : it]})	
}
public Observable getVideoSummary(APIVideo video) {	
// get id, title	
def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)]	

!
// get bookmark	
def bookmarkObservable = getBookmark(video)	

!
// get artwork	
def artworkObservable = getArtworkImageUrl(video)	

!
// merge them and accumulate into the seed.	
return Observable.merge(bookmarkObservable, artworkObservable)	
.reduce(seed, { aggregate, current -> aggregate << current})	
.map({ [ (video.id.toString()) : it]})	
}
public Observable getVideoSummary(APIVideo video) {	
// get id, title	
def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)]	

!
// get bookmark	
def bookmarkObservable = getBookmark(video)	

!
// get artwork	
def artworkObservable = getArtworkImageUrl(video)	

!
// merge them and accumulate into the seed.	
return Observable.merge(bookmarkObservable, artworkObservable)	
.reduce(seed, { aggregate, current -> aggregate << current})	
.map({ [ (video.id.toString()) : it]})	
}
$ uploadScript.py -e TEST /test/hello sample.groovy
{
"active": false,
"allocationPercentage": 0,
"creationDate": "Mon Nov 11 05:38:51 UTC 2013",
"revision": 1,
"userAuthorizationRequired": true,
"userAuthorizationType": "https"
}
$ uploadScript.py -e TEST /test/hello sample.groovy
{
"active": false,
"allocationPercentage": 0,
"creationDate": "Mon Nov 11 05:38:51 UTC 2013",
"revision": 1,
"userAuthorizationRequired": true,
"userAuthorizationType": "https"
}
$ uploadScript.py -e TEST /test/hello sample.groovy
{
"active": false,
"allocationPercentage": 0,
"creationDate": "Mon Nov 11 05:40:26 UTC 2013",
"revision": 2,
"userAuthorizationRequired": true,
"userAuthorizationType": "https"
}
$ uploadScript.py -e TEST /test/hello sample.groovy
{
"active": false,
"allocationPercentage": 0,
"creationDate": "Mon Nov 11 05:40:26 UTC 2013",
"revision": 2,
"userAuthorizationRequired": true,
"userAuthorizationType": "https"
}
$ activateScript.py -e TEST --revision 2 /test/hello
{
"active": true,
"allocationPercentage": 100,
"creationDate": "Mon Nov 11 05:40:26 UTC 2013",
"previousRevision": null,
"revision": 2,
"userAuthorizationRequired": true,
"userAuthorizationType": "https"
}
$ uploadScript.py -e TEST /test/hello sample.groovy
{
"active": false,
"allocationPercentage": 0,
"creationDate": "Mon Nov 11 05:40:26 UTC 2013",
"revision": 2,
"userAuthorizationRequired": true,
"userAuthorizationType": "https"
}
$ activateScript.py -e TEST --revision 2 /test/hello
{
"active": true,
"allocationPercentage": 100,
"creationDate": "Mon Nov 11 05:40:26 UTC 2013",
"previousRevision": null,
"revision": 2,
"userAuthorizationRequired": true,
"userAuthorizationType": "https"
}
$ uploadScript.py -e TEST /test/hello sample.groovy
{
"active": false,
"allocationPercentage": 0,
"creationDate": "Mon Nov 11 05:40:26 UTC 2013",
"revision": 2,
"userAuthorizationRequired": true,
"userAuthorizationType": "https"
}
$ activateScript.py -e TEST --revision 2 /test/hello
{
"active": true,
"allocationPercentage": 100,
"creationDate": "Mon Nov 11 05:40:26 UTC 2013",
"previousRevision": null,
"revision": 2,
"userAuthorizationRequired": true,
"userAuthorizationType": "https"
}
$ uploadScript.py -e TEST /test/hello sample.groovy
{
"active": false,
"allocationPercentage": 0,
"creationDate": "Mon Nov 11 05:40:26 UTC 2013",
"revision": 2,
"userAuthorizationRequired": true,
"userAuthorizationType": "https"
}
$ activateScript.py -e TEST --revision 2 /test/hello
{
"active": true,
"allocationPercentage": 100,
"creationDate": "Mon Nov 11 05:40:26 UTC 2013",
"previousRevision": null,
"revision": 2,
"userAuthorizationRequired": true,
"userAuthorizationType": "https"
}
$ uploadScript.py -e TEST /test/hello sample.groovy
{
"active": false,
"allocationPercentage": 0,
"creationDate": "Mon Nov 11 05:40:26 UTC 2013",
"revision": 2,
"userAuthorizationRequired": true,
"userAuthorizationType": "https"
}
$ activateScript.py -e TEST --revision 3 /test/hello
{
"active": true,
"allocationPercentage": 100,
"creationDate": "Mon Nov 11 05:42:05 UTC 2013",
"previousRevision": 2,
"revision": 3,
"userAuthorizationRequired": true,
"userAuthorizationType": "https"
}
Future
millions of API requests per day

2000

1500

1000

500

0
2008

2009

2010

2011

2012

Today
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
Evolution of the Netflix API
/tv/home

/android/home

/ps3/home

Functional Reactive Dynamic Endpoints

Asynchronous Java API

Dependency A
10 Threads

Dependency F
10 Threads

Dependency K
15 Threads

Dependency P
10 Threads

Dependency B
8 Threads

Dependency G
10 Threads

Dependency L
4 Threads

Dependency Q
8 Threads

Dependency C
10 Threads

Dependency H
10 Threads

Dependency M
5 Threads

Dependency R
10 Threads

Dependency D
15 Threads

Dependency I
5 Threads

Dependency N
10 Threads

Dependency S
8 Threads

Dependency E
5 Threads

Dependency J
8 Threads

Dependency O
10 Threads

Dependency T
10 Threads
/tv/home

/android/home

/ps3/home

Hystrix

Functional Reactive Dynamic Endpoints

fault-isolation layer

Asynchronous Java API

Dependency A
10 Threads

Dependency F
10 Threads

Dependency K
15 Threads

Dependency P
10 Threads

Dependency B
8 Threads

Dependency G
10 Threads

Dependency L
4 Threads

Dependency Q
8 Threads

Dependency C
10 Threads

Dependency H
10 Threads

Dependency M
5 Threads

Dependency R
10 Threads

Dependency D
15 Threads

Dependency I
5 Threads

Dependency N
10 Threads

Dependency S
8 Threads

Dependency E
5 Threads

Dependency J
8 Threads

Dependency O
10 Threads

Dependency T
10 Threads
+
Observable<User>	
  u	
  =	
  new	
  GetUserCommand(id).observe();	
  
Observable<Geo>	
  g	
  =	
  new	
  GetGeoCommand(request).observe();	
  
!
Observable.zip(u,	
  g,	
  {user,	
  geo	
  -­‐>	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  [username:	
  user.getUsername(),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  currentLocation:	
  geo.getCounty()]	
  	
  	
  	
  
})

RxJava in Hystrix 1.3+
https://github.com/Netflix/Hystrix
Evolution of the Netflix API
Evolution of the Netflix API
Ben Christensen
@benjchristensen
http://www.linkedin.com/in/benjchristensen

jobs.netflix.com

!

Functional Reactive in the Netflix API with RxJava
http://techblog.netflix.com/2013/02/rxjava-netflix-api.html

!

Optimizing the Netflix API
http://techblog.netflix.com/2013/01/optimizing-netflix-api.html

!

Application Resilience in a Service-oriented Architecture
http://programming.oreilly.com/2013/06/application-resilience-in-a-service-oriented-architecture.html

!

Fault Tolerance in a High Volume, Distributed System
http://techblog.netflix.com/2012/02/fault-tolerance-in-high-volume.html

!

Making the Netflix API More Resilient
http://techblog.netflix.com/2011/12/making-netflix-api-more-resilient.html
Watch the video with slide synchronization on
InfoQ.com!
http://www.infoq.com/presentations/netflixapi-evolution

Más contenido relacionado

Similar a Evolution of the Netflix API

Stranger Things: The Forces that Disrupt Netflix
Stranger Things: The Forces that Disrupt NetflixStranger Things: The Forces that Disrupt Netflix
Stranger Things: The Forces that Disrupt NetflixC4Media
 
Pros and Cons of a MicroServices Architecture talk at AWS ReInvent
Pros and Cons of a MicroServices Architecture talk at AWS ReInventPros and Cons of a MicroServices Architecture talk at AWS ReInvent
Pros and Cons of a MicroServices Architecture talk at AWS ReInventSudhir Tonse
 
Mastering Chaos - A Netflix Guide to Microservices
Mastering Chaos - A Netflix Guide to MicroservicesMastering Chaos - A Netflix Guide to Microservices
Mastering Chaos - A Netflix Guide to MicroservicesC4Media
 
Generating Unified APIs with Protocol Buffers and gRPC
Generating Unified APIs with Protocol Buffers and gRPCGenerating Unified APIs with Protocol Buffers and gRPC
Generating Unified APIs with Protocol Buffers and gRPCC4Media
 
Netflix Edge Engineering Open House Presentations - June 9, 2016
Netflix Edge Engineering Open House Presentations - June 9, 2016Netflix Edge Engineering Open House Presentations - June 9, 2016
Netflix Edge Engineering Open House Presentations - June 9, 2016Daniel Jacobson
 
QConSF2016-JoshEvans-MasteringChaosANetflixGuidetoMicroservices-compressed.pdf
QConSF2016-JoshEvans-MasteringChaosANetflixGuidetoMicroservices-compressed.pdfQConSF2016-JoshEvans-MasteringChaosANetflixGuidetoMicroservices-compressed.pdf
QConSF2016-JoshEvans-MasteringChaosANetflixGuidetoMicroservices-compressed.pdfSimranjyotSuri
 
Next Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileNext Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileC4Media
 
Netflix Play API: Why we built an evolutionary architecture
Netflix Play API: Why we built an evolutionary architectureNetflix Play API: Why we built an evolutionary architecture
Netflix Play API: Why we built an evolutionary architectureSuudhan Rangarajan
 
Scalable Microservices at Netflix. Challenges and Tools of the Trade
Scalable Microservices at Netflix. Challenges and Tools of the TradeScalable Microservices at Netflix. Challenges and Tools of the Trade
Scalable Microservices at Netflix. Challenges and Tools of the TradeC4Media
 
Mastering Chaos - A Netflix Guide to Microservices
Mastering Chaos - A Netflix Guide to MicroservicesMastering Chaos - A Netflix Guide to Microservices
Mastering Chaos - A Netflix Guide to MicroservicesJosh Evans
 
(PFC304) Effective Interprocess Communications in the Cloud: The Pros and Con...
(PFC304) Effective Interprocess Communications in the Cloud: The Pros and Con...(PFC304) Effective Interprocess Communications in the Cloud: The Pros and Con...
(PFC304) Effective Interprocess Communications in the Cloud: The Pros and Con...Amazon Web Services
 
Have Your Cake and Eat It Too -- Further Dispelling the Myths of the Lambda A...
Have Your Cake and Eat It Too -- Further Dispelling the Myths of the Lambda A...Have Your Cake and Eat It Too -- Further Dispelling the Myths of the Lambda A...
Have Your Cake and Eat It Too -- Further Dispelling the Myths of the Lambda A...C4Media
 
The Service Mesh: It's about Traffic
The Service Mesh: It's about TrafficThe Service Mesh: It's about Traffic
The Service Mesh: It's about TrafficC4Media
 
Fault Tolerance at Speed
Fault Tolerance at SpeedFault Tolerance at Speed
Fault Tolerance at SpeedC4Media
 
Microservices: State of the Union
Microservices: State of the UnionMicroservices: State of the Union
Microservices: State of the UnionC4Media
 
Building a Bank with Go
Building a Bank with GoBuilding a Bank with Go
Building a Bank with GoC4Media
 
Road to REST
Road to RESTRoad to REST
Road to RESTC4Media
 
Scaling Push Messaging for Millions of Devices @Netflix
Scaling Push Messaging for Millions of Devices @NetflixScaling Push Messaging for Millions of Devices @Netflix
Scaling Push Messaging for Millions of Devices @NetflixC4Media
 
Big datadc skyfall_preso_v2
Big datadc skyfall_preso_v2Big datadc skyfall_preso_v2
Big datadc skyfall_preso_v2abramsm
 

Similar a Evolution of the Netflix API (20)

Stranger Things: The Forces that Disrupt Netflix
Stranger Things: The Forces that Disrupt NetflixStranger Things: The Forces that Disrupt Netflix
Stranger Things: The Forces that Disrupt Netflix
 
Pros and Cons of a MicroServices Architecture talk at AWS ReInvent
Pros and Cons of a MicroServices Architecture talk at AWS ReInventPros and Cons of a MicroServices Architecture talk at AWS ReInvent
Pros and Cons of a MicroServices Architecture talk at AWS ReInvent
 
Mastering Chaos - A Netflix Guide to Microservices
Mastering Chaos - A Netflix Guide to MicroservicesMastering Chaos - A Netflix Guide to Microservices
Mastering Chaos - A Netflix Guide to Microservices
 
Generating Unified APIs with Protocol Buffers and gRPC
Generating Unified APIs with Protocol Buffers and gRPCGenerating Unified APIs with Protocol Buffers and gRPC
Generating Unified APIs with Protocol Buffers and gRPC
 
Netflix Edge Engineering Open House Presentations - June 9, 2016
Netflix Edge Engineering Open House Presentations - June 9, 2016Netflix Edge Engineering Open House Presentations - June 9, 2016
Netflix Edge Engineering Open House Presentations - June 9, 2016
 
QConSF2016-JoshEvans-MasteringChaosANetflixGuidetoMicroservices-compressed.pdf
QConSF2016-JoshEvans-MasteringChaosANetflixGuidetoMicroservices-compressed.pdfQConSF2016-JoshEvans-MasteringChaosANetflixGuidetoMicroservices-compressed.pdf
QConSF2016-JoshEvans-MasteringChaosANetflixGuidetoMicroservices-compressed.pdf
 
Next Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileNext Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy Mobile
 
Netflix Play API: Why we built an evolutionary architecture
Netflix Play API: Why we built an evolutionary architectureNetflix Play API: Why we built an evolutionary architecture
Netflix Play API: Why we built an evolutionary architecture
 
Scalable Microservices at Netflix. Challenges and Tools of the Trade
Scalable Microservices at Netflix. Challenges and Tools of the TradeScalable Microservices at Netflix. Challenges and Tools of the Trade
Scalable Microservices at Netflix. Challenges and Tools of the Trade
 
Mastering Chaos - A Netflix Guide to Microservices
Mastering Chaos - A Netflix Guide to MicroservicesMastering Chaos - A Netflix Guide to Microservices
Mastering Chaos - A Netflix Guide to Microservices
 
(PFC304) Effective Interprocess Communications in the Cloud: The Pros and Con...
(PFC304) Effective Interprocess Communications in the Cloud: The Pros and Con...(PFC304) Effective Interprocess Communications in the Cloud: The Pros and Con...
(PFC304) Effective Interprocess Communications in the Cloud: The Pros and Con...
 
Have Your Cake and Eat It Too -- Further Dispelling the Myths of the Lambda A...
Have Your Cake and Eat It Too -- Further Dispelling the Myths of the Lambda A...Have Your Cake and Eat It Too -- Further Dispelling the Myths of the Lambda A...
Have Your Cake and Eat It Too -- Further Dispelling the Myths of the Lambda A...
 
The Service Mesh: It's about Traffic
The Service Mesh: It's about TrafficThe Service Mesh: It's about Traffic
The Service Mesh: It's about Traffic
 
Fault Tolerance at Speed
Fault Tolerance at SpeedFault Tolerance at Speed
Fault Tolerance at Speed
 
Microservices: State of the Union
Microservices: State of the UnionMicroservices: State of the Union
Microservices: State of the Union
 
Building a Bank with Go
Building a Bank with GoBuilding a Bank with Go
Building a Bank with Go
 
Road to REST
Road to RESTRoad to REST
Road to REST
 
Edge architecture ieee international conference on cloud engineering
Edge architecture   ieee international conference on cloud engineeringEdge architecture   ieee international conference on cloud engineering
Edge architecture ieee international conference on cloud engineering
 
Scaling Push Messaging for Millions of Devices @Netflix
Scaling Push Messaging for Millions of Devices @NetflixScaling Push Messaging for Millions of Devices @Netflix
Scaling Push Messaging for Millions of Devices @Netflix
 
Big datadc skyfall_preso_v2
Big datadc skyfall_preso_v2Big datadc skyfall_preso_v2
Big datadc skyfall_preso_v2
 

Más de C4Media

Streaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoStreaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoC4Media
 
Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020C4Media
 
Understand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsUnderstand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsC4Media
 
Kafka Needs No Keeper
Kafka Needs No KeeperKafka Needs No Keeper
Kafka Needs No KeeperC4Media
 
High Performing Teams Act Like Owners
High Performing Teams Act Like OwnersHigh Performing Teams Act Like Owners
High Performing Teams Act Like OwnersC4Media
 
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaDoes Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaC4Media
 
Service Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideService Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideC4Media
 
Shifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDShifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDC4Media
 
CI/CD for Machine Learning
CI/CD for Machine LearningCI/CD for Machine Learning
CI/CD for Machine LearningC4Media
 
Architectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsArchitectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsC4Media
 
ML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsC4Media
 
Build Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerBuild Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerC4Media
 
User & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleUser & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleC4Media
 
Scaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeScaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeC4Media
 
Make Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereMake Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereC4Media
 
The Talk You've Been Await-ing For
The Talk You've Been Await-ing ForThe Talk You've Been Await-ing For
The Talk You've Been Await-ing ForC4Media
 
Future of Data Engineering
Future of Data EngineeringFuture of Data Engineering
Future of Data EngineeringC4Media
 
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreAutomated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreC4Media
 
Navigating Complexity: High-performance Delivery and Discovery Teams
Navigating Complexity: High-performance Delivery and Discovery TeamsNavigating Complexity: High-performance Delivery and Discovery Teams
Navigating Complexity: High-performance Delivery and Discovery TeamsC4Media
 
High Performance Cooperative Distributed Systems in Adtech
High Performance Cooperative Distributed Systems in AdtechHigh Performance Cooperative Distributed Systems in Adtech
High Performance Cooperative Distributed Systems in AdtechC4Media
 

Más de C4Media (20)

Streaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoStreaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live Video
 
Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020
 
Understand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsUnderstand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java Applications
 
Kafka Needs No Keeper
Kafka Needs No KeeperKafka Needs No Keeper
Kafka Needs No Keeper
 
High Performing Teams Act Like Owners
High Performing Teams Act Like OwnersHigh Performing Teams Act Like Owners
High Performing Teams Act Like Owners
 
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaDoes Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
 
Service Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideService Meshes- The Ultimate Guide
Service Meshes- The Ultimate Guide
 
Shifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDShifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CD
 
CI/CD for Machine Learning
CI/CD for Machine LearningCI/CD for Machine Learning
CI/CD for Machine Learning
 
Architectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsArchitectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep Systems
 
ML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.js
 
Build Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerBuild Your Own WebAssembly Compiler
Build Your Own WebAssembly Compiler
 
User & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleUser & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix Scale
 
Scaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeScaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's Edge
 
Make Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereMake Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home Everywhere
 
The Talk You've Been Await-ing For
The Talk You've Been Await-ing ForThe Talk You've Been Await-ing For
The Talk You've Been Await-ing For
 
Future of Data Engineering
Future of Data EngineeringFuture of Data Engineering
Future of Data Engineering
 
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreAutomated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
 
Navigating Complexity: High-performance Delivery and Discovery Teams
Navigating Complexity: High-performance Delivery and Discovery TeamsNavigating Complexity: High-performance Delivery and Discovery Teams
Navigating Complexity: High-performance Delivery and Discovery Teams
 
High Performance Cooperative Distributed Systems in Adtech
High Performance Cooperative Distributed Systems in AdtechHigh Performance Cooperative Distributed Systems in Adtech
High Performance Cooperative Distributed Systems in Adtech
 

Último

Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxGDSC PJATK
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-pyJamie (Taka) Wang
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7DianaGray10
 
Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Brian Pichman
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfAijun Zhang
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfinfogdgmi
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsSeth Reyes
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesMd Hossain Ali
 
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfUiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfDianaGray10
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopBachir Benyammi
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UbiTrack UK
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1DianaGray10
 
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationUsing IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationIES VE
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024SkyPlanner
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Commit University
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfJamie (Taka) Wang
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioChristian Posta
 

Último (20)

Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptx
 
20230104 - machine vision
20230104 - machine vision20230104 - machine vision
20230104 - machine vision
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-py
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7
 
Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdf
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdf
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and Hazards
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
 
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfUiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 Workshop
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1
 
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationUsing IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and Istio
 

Evolution of the Netflix API

  • 1. Evolution of the Netflix API QCon San Francisco - November 2013 Ben Christensen Software Engineer – Edge & Playback Services at Netflix @benjchristensen ! ! ! ! http://techblog.netflix.com/
  • 2. Watch the video with slide synchronization on InfoQ.com! http://www.infoq.com/presentations /netflix-api-evolution InfoQ.com: News & Community Site • 750,000 unique visitors/month • Published in 4 languages (English, Chinese, Japanese and Brazilian Portuguese) • Post content from our QCon conferences • News 15-20 / week • Articles 3-4 / week • Presentations (videos) 12-15 / week • Interviews 2-3 / week • Books 1 / month
  • 3. Presented at QCon San Francisco www.qconsf.com Purpose of QCon - to empower software development by facilitating the spread of knowledge and innovation Strategy - practitioner-driven conference designed for YOU: influencers of change and innovation in your teams - speakers and topics driving the evolution and innovation - connecting and catalyzing the influencers and innovators Highlights - attended by more than 12,000 delegates since 2007 - held in 9 cities worldwide
  • 5. More than 40 million Subscribers in 50+ Countries and Territories
  • 6. Netflix accounts for 33% of Peak Downstream Internet Traffic in North America Netflix subscribers are watching more than 1 billion hours a month
  • 7. API traffic has grown from ~20 million/day in 2010 to >2 billion/day millions of API requests per day 2000 1500 1000 500 0 2010 2011 2012 Today
  • 11. At the start … millions of API requests per day 2000 1500 1000 500 0 2008 2009 2010 2011 2012 Today
  • 12. 2008 API Launch Targeted 100% at External Developers Open API Netflix Devices
  • 13. 2008 API Launch Targeted 100% at External Developers Purpose A “Thousand Flowers” of 3rd party innovation ! Audience External Developers
  • 15. In 2011 … millions of API requests per day 2000 1500 1000 500 0 2008 2009 2010 2011 2012 Today
  • 16. 99.9% Netflix Devices Open API Netflix Devices
  • 17. Targeted at Internal Developers Open API Netflix Devices
  • 18. Targeted at Internal Developers Purpose Enable Netflix Experience ! Audience Netflix Device and UI Teams
  • 21. Netflix API Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R
  • 22. Netflix API Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R
  • 32. User Request Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R
  • 33. User Request Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R User request blocked by latency in single network call
  • 34. Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R User Request User Request User Request User Request User Request User Request User Request ............................................. At high volume all request threads can block in seconds
  • 35. ! Dozens of dependencies. ! One going bad takes everything down. ! 30 99.99% = 99.7% uptime ! 0.3% of 1 billion = 3,000,000 failures ! 2+ hours downtime/month ! ! ! Reality is generally worse.
  • 36. CONSTRAINTS Speed of Iteration ! Client Libraries ! Mixed Environment
  • 37. CONSTRAINTS Speed of Iteration ! Client Libraries ! Mixed Environment
  • 38. CONSTRAINTS Speed of Iteration ! Client Libraries ! Mixed Environment
  • 39. CONSTRAINTS Speed of Iteration ! Client Libraries ! Mixed Environment
  • 40. Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R User Request User Request User Request User Request User Request User Request User Request .............................................
  • 41. User Request User Request User Request Logic - argument validation, caches, metrics, logging, multivariate testing, routing, etc Serialization - URL and/or body generation Network Request - TCP/HTTP, latency, 4xx, 5xx, etc ............................................. Deserialization - JSON/XML/Thrift/Protobuf/etc Dependency B cy D Dependency C Dependency E dency G ependency J Dependency M Logic - validation, decoration, object model, caching, metrics, logging, etc Dependency F Dependency H Dependency K Dependency N Dependency I Dependency L Dependency O
  • 42. > 80% of requests rejected Median Latency [Sat Jun 30 04:01:37 2012] [error] proxy: HTTP: disabled connection for (127.0.0.1) "Timeout guard" daemon prio=10 tid=0x00002aaacd5e5000 nid=0x3aac runnable [0x00002aaac388f000] java.lang.Thread.State: RUNNABLE! at java.net.PlainSocketImpl.socketConnect(Native Method)! at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)! - locked <0x000000055c7e8bd8> (a java.net.SocksSocketImpl)! at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)! at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)! at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)! at java.net.Socket.connect(Socket.java:579)! at java.net.Socket.connect(Socket.java:528)! at java.net.Socket.(Socket.java:425)! at java.net.Socket.(Socket.java:280)! at org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory.createSocket(DefaultProtocolSocketFactory.java:80)! at org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory$1.doit(ControllerThreadSocketFactory.java:91)! at org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory$SocketTask.run(ControllerThreadSocketFactory.java:158) at java.lang.Thread.run(Thread.java:722)
  • 43. User Request Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R
  • 44. User Request Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R
  • 45. User Request Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R
  • 46. User Request Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R
  • 50. circle color and size represent health and traffic volume
  • 51. circle color and size represent health and traffic volume 2 minutes of request rate to show relative changes in traffic
  • 52. circle color and size represent health and traffic volume 2 minutes of request rate to show relative changes in traffic hosts reporting from cluster
  • 53. circle color and size represent health and traffic volume 2 minutes of request rate to show relative changes in traffic hosts reporting from cluster last minute latency percentiles
  • 54. circle color and size represent health and traffic volume 2 minutes of request rate to show relative changes in traffic hosts reporting from cluster Circuit-breaker status last minute latency percentiles
  • 55. circle color and size represent health and traffic volume Request rate 2 minutes of request rate to show relative changes in traffic hosts reporting from cluster Circuit-breaker status last minute latency percentiles
  • 56. circle color and size represent health and traffic volume Error percentage of last 10 seconds Request rate 2 minutes of request rate to show relative changes in traffic hosts reporting from cluster Circuit-breaker status last minute latency percentiles
  • 57. Error percentage of last 10 seconds circle color and size represent health and traffic volume Request rate 2 minutes of request rate to show relative changes in traffic Circuit-breaker status hosts reporting from cluster last minute latency percentiles Rolling 10 second counters with 1 second granularity Successes Short-circuited (rejected) Thread timeouts Thread-pool Rejections Failures/Exceptions
  • 58. User Request Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R
  • 60. Zuul Routing Layer Canary vs Baseline Squeeze "Coalmine" Production
  • 61. Zuul Routing Layer Canary vs Baseline Squeeze "Coalmine" Production
  • 62. Zuul Routing Layer Canary vs Baseline Squeeze "Coalmine" Production
  • 63. Zuul Routing Layer Canary vs Baseline Squeeze "Coalmine" Production
  • 64. Zuul Routing Layer Canary vs Baseline Squeeze "Coalmine" Production
  • 65. User Request Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R System Relationship Over Network without Bulkhead
  • 66. Zuul Routing Layer Canary vs Baseline Squeeze "Coalmine" Production
  • 67. Zuul Routing Layer Canary vs Baseline Squeeze "Coalmine" Production
  • 76. Predictive + Reactive Auto-Scaling
  • 86. Netflix API Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R
  • 87. Netflix API Dependency A Dependency B Dependency D Dependency C Dependency E Dependency G Dependency F Dependency H Dependency J Dependency M Dependency P Dependency I Dependency K Dependency N Dependency Q Dependency L Dependency O Dependency R
  • 88. One Size Fits All RESTful API millions of API requests per day 2000 1500 1000 500 0 2010 2011 2012 Today
  • 89. One Size Fits All RESTful API millions of API requests per day 2000 1500 1000 500 0 2010 2011 2012 Today
  • 90. One Size Fits All RESTful API 1000+ Devices millions of API requests per day 2000 1500 1000 500 0 2010 2011 2012 Today
  • 91. We wanted to re-architecture our call patterns ...
  • 92. ... to collapse network traffic into coarse API calls ... nested, conditional, concurrent execution
  • 93. ... and we wanted to allow anybody to create endpoints, not just the “API Team”
  • 95. Concurrency without each engineer reading and re-reading this → ! (awesome book ... everybody isn’t going to - or should have to - read it though, that’s the point)
  • 96. Owner of api should retain control of concurrency behavior.
  • 97. Owner of api should retain control of concurrency behavior. public  Data  getData(); What if the implementation needs to change from synchronous to asynchronous? ! How should the client execute that method without blocking? spawn a thread?
  • 98. public  Data  getData(); public  void  getData(Callback<T>  c);   ! public  Future<T>  getData();   ! public  Future<List<Future<T>>>  getData();   ! ! other options ... ?
  • 99. Reactive Programming with Rx Iterable pull T next() throws Exception returns; Observable push onNext(T) onError(Exception) onCompleted()
  • 100. (Functional) Reactive Programming with RxJava Iterable pull T next() throws Exception returns; Observable push onNext(T) onError(Exception) onCompleted()
  • 101. (Functional) Reactive Programming with RxJava Iterable pull T next() throws Exception returns; Observable push onNext(T) onError(Exception) onCompleted()
  • 102. (Functional) Reactive Programming with RxJava Iterable pull T next() throws Exception returns; Observable push onNext(T) onError(Exception) onCompleted()
  • 103. Iterable pull T next() throws Exception returns; !  //  Iterable<String>      //  that  contains  75  Strings    getDataFromLocalMemory()      .skip(10)      .take(5)      .map({  s  -­‐>          return  s  +  "_transformed"})      .forEach(            {  println  "next  =>  "  +  it})   Observable push onNext(T) onError(Exception) onCompleted() !  //  Observable<String>      //  that  emits  75  Strings    getDataFromNetwork()      .skip(10)      .take(5)      .map({  s  -­‐>          return  s  +  "_transformed"})      .subscribe(            {  println  "onNext  =>  "  +  it})  
  • 104. Iterable pull T next() throws Exception returns; !  //  Iterable<String>      //  that  contains  75  Strings    getDataFromLocalMemory()      .skip(10)      .take(5)      .map({  s  -­‐>          return  s  +  "_transformed"})      .forEach(            {  println  "onNext  =>  "  +  it})   Observable push onNext(T) onError(Exception) onCompleted() !  //  Observable<String>      //  that  emits  75  Strings    getDataFromNetwork()      .skip(10)      .take(5)      .map({  s  -­‐>          return  s  +  "_transformed"})      .subscribe(            {  println  "onNext  =>  "  +  it})  
  • 106. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() String s = getData(args); if (s.equals(x)) { // do something } else { // do something else }
  • 107. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() Iterable<String> values = getData(args); for (String s : values) { if (s.equals(x)) { // do something } else { // do something else } }
  • 108. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() Future<String> s = getData(args); if (s.get().equals(x)) { // do something } else { // do something else }
  • 109. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() Future<String> s = getData(args); if (s.get().equals(x)) { // do something } else { // do something else }
  • 110. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() Future<String> s = getData(args); Futures.addCallback(s, new FutureCallback<String> { public void onSuccess(String s) { if (s.equals(x)) { // do something } else { // do something else } } }, executor);
  • 111. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() Future<String> s = getData(args); Futures.addCallback(s, new FutureCallback<String> { public void onSuccess(String s) { if (s.equals(x)) { // do something } else { // do something else } } }, executor);
  • 112. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() Future<String> s = getData(args); Futures.addCallback(s, new FutureCallback<String> { public void onSuccess(String s) { if (s.equals(x)) { // do something } else { // do something else } } }, executor);
  • 113. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() CompletableFuture<String> s = getData(args); s.thenApply((v) -> { if (v.equals(x)) { // do something } else { // do something else } });
  • 114. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() CompletableFuture<String> s = getData(args); s.thenApply((v) -> { if (v.equals(x)) { // do something } else { // do something else } });
  • 115. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() Future<String> s = getData(args); s.map({ s -> if (s.equals(x)) { // do something } else { // do something else } });
  • 116. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() Future<String> s = getData(args); s.map({ s -> if (s.equals(x)) { // do something } else { // do something else } });
  • 117. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() Future<String> s = getData(args); s.map({ s -> if (s.equals(x)) { // do something } else { // do something else } });
  • 118. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() Observable<String> s = getData(args); s.map({ s -> if (s.equals(x)) { // do something } else { // do something else } });
  • 119. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() Observable<String> s = getData(args); s.map({ s -> if (s.equals(x)) { // do something } else { // do something else } });
  • 120. Single Multiple Sync T getData() Iterable<T> getData() Async Future<T> getData() Observable<T> getData() Observable<String> s = getData(args); s.map({ s -> if (s.equals(x)) { // do something } else { // do something else } });
  • 121. instead of a blocking api ... class  VideoService  {        def  VideoList  getPersonalizedListOfMovies(userId);        def  VideoBookmark  getBookmark(userId,  videoId);        def  VideoRating  getRating(userId,  videoId);        def  VideoMetadata  getMetadata(videoId);   } ... create an observable api: class  VideoService  {        def  Observable<VideoList>  getPersonalizedListOfMovies(userId);        def  Observable<VideoBookmark>  getBookmark(userId,  videoId);        def  Observable<VideoRating>  getRating(userId,  videoId);        def  Observable<VideoMetadata>  getMetadata(videoId);   }
  • 122. RxJava http://github.com/Netflix/RxJava “a library for composing asynchronous and event-based programs using observable sequences for the Java VM” A Java port of Rx (Reactive Extensions) https://rx.codeplex.com (.Net and Javascript by Microsoft)
  • 123. client code treats all interactions with the api as asynchronous ! ! the api implementation chooses whether something is blocking or non-blocking and what resources it uses
  • 130. Netflix API Server Device Optimize for Each Device. Leverage the Server
  • 131. Code
  • 132. SDK for API Web Service Development
  • 133. SDK for API Web Service Development
  • 134. SDK for API Web Service Development
  • 136. api.servletResponse.writer.print("Hello") $runScript.py -e PROD sample.groovy Hello ################################################################################################ ####### Script Logger (enabled via debug=true request parameter) ################################################################################################ [0ms] INFO: User => NULL ################################################################################################ ####### Script Logger (enabled via debug=true request parameter) ################################################################################################
  • 137. api.servletResponse.writer.print("Hello") $runScript.py -e PROD sample.groovy Hello ################################################################################################ ####### Script Logger (enabled via debug=true request parameter) ################################################################################################ [0ms] INFO: User => NULL ################################################################################################ ####### Script Logger (enabled via debug=true request parameter) ################################################################################################
  • 138. api.servletResponse.writer.print("Hello") $runScript.py -e PROD sample.groovy Hello ################################################################################################ ####### Script Logger (enabled via debug=true request parameter) ################################################################################################ [0ms] INFO: User => NULL ################################################################################################ ####### Script Logger (enabled via debug=true request parameter) ################################################################################################
  • 139. api.servletResponse.writer.print("Hello") $runScript.py -e PROD sample.groovy Hello ################################################################################################ ####### Script Logger (enabled via debug=true request parameter) ################################################################################################ [0ms] INFO: User => NULL ################################################################################################ ####### Script Logger (enabled via debug=true request parameter) ################################################################################################
  • 140. api.servletResponse.writer.print("Hello") $runScript.py -e PROD sample.groovy Hello ################################################################################################ ####### Script Logger (enabled via debug=true request parameter) ################################################################################################ [0ms] INFO: User => NULL ################################################################################################ ####### Script Logger (enabled via debug=true request parameter) ################################################################################################
  • 141. api.servletResponse.writer.print("Hello") $runScript.py -e PROD sample.groovy Hello ################################################################################################ ####### Script Logger (enabled via debug=true request parameter) ################################################################################################ [0ms] INFO: User => NULL ################################################################################################ ####### Script Logger (enabled via debug=true request parameter) ################################################################################################
  • 142. public class HelloEndpoint extends APIEndpoint { @Override public void execute(APIRequest api) throws Throwable { // get a request parameter from servlet request String alias = api.servletRequest.getParameter("name"); ! // set content type and write something to servlet response api.servletResponse.setContentType("application/json"); api.servletResponse.writer.print( JsonUtility.toJson( [ alias : alias, name : api.user.firstName ] ) ) ! } }
  • 143. public class HelloEndpoint extends APIEndpoint { @Override public void execute(APIRequest api) throws Throwable { // get a request parameter from servlet request String alias = api.servletRequest.getParameter("name"); ! // set content type and write something to servlet response api.servletResponse.setContentType("application/json"); api.servletResponse.writer.print( JsonUtility.toJson( [ alias : alias, name : api.user.firstName ] ) ) ! } } runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy
  • 144. public class HelloEndpoint extends APIEndpoint { @Override public void execute(APIRequest api) throws Throwable { // get a request parameter from servlet request String alias = api.servletRequest.getParameter("name"); ! // set content type and write something to servlet response api.servletResponse.setContentType("application/json"); api.servletResponse.writer.print( JsonUtility.toJson( [ alias : alias, name : api.user.firstName ] ) ) ! } } runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy {"alias":"bob","name":"Old"}
  • 145. public class HelloEndpoint extends APIEndpoint { @Override public void execute(APIRequest api) throws Throwable { // get a request parameter from servlet request String alias = api.servletRequest.getParameter("name"); ! // set content type and write something to servlet response api.servletResponse.setContentType("application/json"); api.servletResponse.writer.print( JsonUtility.toJson( [ alias : alias, name : api.user.firstName ] ) ) ! } } runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy {"alias":"bob","name":"Old"}
  • 146. public class HelloEndpoint extends APIEndpoint { @Override public void execute(APIRequest api) throws Throwable { // get a request parameter from servlet request String alias = api.servletRequest.getParameter("name"); ! // set content type and write something to servlet response api.servletResponse.setContentType("application/json"); api.servletResponse.writer.print( JsonUtility.toJson( [ alias : alias, name : api.user.firstName ] ) ) ! } } runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy {"alias":"bob","name":"Old"}
  • 147. public class HelloEndpoint extends APIEndpoint { @Override public void execute(APIRequest api) throws Throwable { // get a request parameter from servlet request String alias = api.servletRequest.getParameter("name"); ! // set content type and write something to servlet response api.servletResponse.setContentType("application/json"); api.servletResponse.writer.print( JsonUtility.toJson( [ alias : alias, name : api.user.firstName ] ) ) ! } } runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy {"alias":"bob","name":"Old"}
  • 148. public class HelloEndpoint extends APIEndpoint { @Override public void execute(APIRequest api) throws Throwable { // get a request parameter from servlet request String alias = api.servletRequest.getParameter("name"); ! // set content type and write something to servlet response api.servletResponse.setContentType("application/json"); api.servletResponse.writer.print( JsonUtility.toJson( [ alias : alias, name : api.user.firstName ] ) ) ! } } runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy {"alias":"bob","name":"Old"}
  • 149. public class HelloEndpoint extends APIEndpoint { @Override public void execute(APIRequest api) throws Throwable { // get a request parameter from servlet request String alias = api.servletRequest.getParameter("name"); ! // set content type and write something to servlet response api.servletResponse.setContentType("application/json"); api.servletResponse.writer.print( JsonUtility.toJson( [ alias : alias, name : api.user.firstName ] ) ) ! } } runScript.py -e TEST --userId 1189658154 --args "name=bob" HelloEndpoint.groovy {"alias":"bob","name":"Old"}
  • 150. public Observable getVideoSummary(APIVideo video) { // get id, title def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)] ! // get bookmark def bookmarkObservable = getBookmark(video) ! // get artwork def artworkObservable = getArtworkImageUrl(video) ! // merge them and accumulate into the seed. return Observable.merge(bookmarkObservable, artworkObservable) .reduce(seed, { aggregate, current -> aggregate << current}) .map({ [ (video.id.toString()) : it]}) }
  • 151. public Observable getVideoSummary(APIVideo video) { // get id, title def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)] ! // get bookmark def bookmarkObservable = getBookmark(video) ! // get artwork def artworkObservable = getArtworkImageUrl(video) ! // merge them and accumulate into the seed. return Observable.merge(bookmarkObservable, artworkObservable) .reduce(seed, { aggregate, current -> aggregate << current}) .map({ [ (video.id.toString()) : it]}) }
  • 152. public Observable getVideoSummary(APIVideo video) { // get id, title def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)] ! // get bookmark def bookmarkObservable = getBookmark(video) ! // get artwork def artworkObservable = getArtworkImageUrl(video) ! // merge them and accumulate into the seed. return Observable.merge(bookmarkObservable, artworkObservable) .reduce(seed, { aggregate, current -> aggregate << current}) .map({ [ (video.id.toString()) : it]}) }
  • 153. public Observable getVideoSummary(APIVideo video) { // get id, title def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)] ! // get bookmark def bookmarkObservable = getBookmark(video) ! // get artwork def artworkObservable = getArtworkImageUrl(video) ! // merge them and accumulate into the seed. return Observable.merge(bookmarkObservable, artworkObservable) .reduce(seed, { aggregate, current -> aggregate << current}) .map({ [ (video.id.toString()) : it]}) }
  • 154. public Observable getVideoSummary(APIVideo video) { // get id, title def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)] ! // get bookmark def bookmarkObservable = getBookmark(video) ! // get artwork def artworkObservable = getArtworkImageUrl(video) ! // merge them and accumulate into the seed. return Observable.merge(bookmarkObservable, artworkObservable) .reduce(seed, { aggregate, current -> aggregate << current}) .map({ [ (video.id.toString()) : it]}) }
  • 155. public Observable getVideoSummary(APIVideo video) { // get id, title def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)] ! // get bookmark def bookmarkObservable = getBookmark(video) ! // get artwork def artworkObservable = getArtworkImageUrl(video) ! // merge them and accumulate into the seed. return Observable.merge(bookmarkObservable, artworkObservable) .reduce(seed, { aggregate, current -> aggregate << current}) .map({ [ (video.id.toString()) : it]}) }
  • 156. public Observable getVideoSummary(APIVideo video) { // get id, title def seed = [id: video.id, title : video.getTitle(APIVideo.TitleType.REGULAR)] ! // get bookmark def bookmarkObservable = getBookmark(video) ! // get artwork def artworkObservable = getArtworkImageUrl(video) ! // merge them and accumulate into the seed. return Observable.merge(bookmarkObservable, artworkObservable) .reduce(seed, { aggregate, current -> aggregate << current}) .map({ [ (video.id.toString()) : it]}) }
  • 157. $ uploadScript.py -e TEST /test/hello sample.groovy { "active": false, "allocationPercentage": 0, "creationDate": "Mon Nov 11 05:38:51 UTC 2013", "revision": 1, "userAuthorizationRequired": true, "userAuthorizationType": "https" }
  • 158. $ uploadScript.py -e TEST /test/hello sample.groovy { "active": false, "allocationPercentage": 0, "creationDate": "Mon Nov 11 05:38:51 UTC 2013", "revision": 1, "userAuthorizationRequired": true, "userAuthorizationType": "https" }
  • 159. $ uploadScript.py -e TEST /test/hello sample.groovy { "active": false, "allocationPercentage": 0, "creationDate": "Mon Nov 11 05:40:26 UTC 2013", "revision": 2, "userAuthorizationRequired": true, "userAuthorizationType": "https" }
  • 160. $ uploadScript.py -e TEST /test/hello sample.groovy { "active": false, "allocationPercentage": 0, "creationDate": "Mon Nov 11 05:40:26 UTC 2013", "revision": 2, "userAuthorizationRequired": true, "userAuthorizationType": "https" } $ activateScript.py -e TEST --revision 2 /test/hello { "active": true, "allocationPercentage": 100, "creationDate": "Mon Nov 11 05:40:26 UTC 2013", "previousRevision": null, "revision": 2, "userAuthorizationRequired": true, "userAuthorizationType": "https" }
  • 161. $ uploadScript.py -e TEST /test/hello sample.groovy { "active": false, "allocationPercentage": 0, "creationDate": "Mon Nov 11 05:40:26 UTC 2013", "revision": 2, "userAuthorizationRequired": true, "userAuthorizationType": "https" } $ activateScript.py -e TEST --revision 2 /test/hello { "active": true, "allocationPercentage": 100, "creationDate": "Mon Nov 11 05:40:26 UTC 2013", "previousRevision": null, "revision": 2, "userAuthorizationRequired": true, "userAuthorizationType": "https" }
  • 162. $ uploadScript.py -e TEST /test/hello sample.groovy { "active": false, "allocationPercentage": 0, "creationDate": "Mon Nov 11 05:40:26 UTC 2013", "revision": 2, "userAuthorizationRequired": true, "userAuthorizationType": "https" } $ activateScript.py -e TEST --revision 2 /test/hello { "active": true, "allocationPercentage": 100, "creationDate": "Mon Nov 11 05:40:26 UTC 2013", "previousRevision": null, "revision": 2, "userAuthorizationRequired": true, "userAuthorizationType": "https" }
  • 163. $ uploadScript.py -e TEST /test/hello sample.groovy { "active": false, "allocationPercentage": 0, "creationDate": "Mon Nov 11 05:40:26 UTC 2013", "revision": 2, "userAuthorizationRequired": true, "userAuthorizationType": "https" } $ activateScript.py -e TEST --revision 2 /test/hello { "active": true, "allocationPercentage": 100, "creationDate": "Mon Nov 11 05:40:26 UTC 2013", "previousRevision": null, "revision": 2, "userAuthorizationRequired": true, "userAuthorizationType": "https" }
  • 164. $ uploadScript.py -e TEST /test/hello sample.groovy { "active": false, "allocationPercentage": 0, "creationDate": "Mon Nov 11 05:40:26 UTC 2013", "revision": 2, "userAuthorizationRequired": true, "userAuthorizationType": "https" } $ activateScript.py -e TEST --revision 3 /test/hello { "active": true, "allocationPercentage": 100, "creationDate": "Mon Nov 11 05:42:05 UTC 2013", "previousRevision": 2, "revision": 3, "userAuthorizationRequired": true, "userAuthorizationType": "https" }
  • 165. Future
  • 166. millions of API requests per day 2000 1500 1000 500 0 2008 2009 2010 2011 2012 Today
  • 174. /tv/home /android/home /ps3/home Functional Reactive Dynamic Endpoints Asynchronous Java API Dependency A 10 Threads Dependency F 10 Threads Dependency K 15 Threads Dependency P 10 Threads Dependency B 8 Threads Dependency G 10 Threads Dependency L 4 Threads Dependency Q 8 Threads Dependency C 10 Threads Dependency H 10 Threads Dependency M 5 Threads Dependency R 10 Threads Dependency D 15 Threads Dependency I 5 Threads Dependency N 10 Threads Dependency S 8 Threads Dependency E 5 Threads Dependency J 8 Threads Dependency O 10 Threads Dependency T 10 Threads
  • 175. /tv/home /android/home /ps3/home Hystrix Functional Reactive Dynamic Endpoints fault-isolation layer Asynchronous Java API Dependency A 10 Threads Dependency F 10 Threads Dependency K 15 Threads Dependency P 10 Threads Dependency B 8 Threads Dependency G 10 Threads Dependency L 4 Threads Dependency Q 8 Threads Dependency C 10 Threads Dependency H 10 Threads Dependency M 5 Threads Dependency R 10 Threads Dependency D 15 Threads Dependency I 5 Threads Dependency N 10 Threads Dependency S 8 Threads Dependency E 5 Threads Dependency J 8 Threads Dependency O 10 Threads Dependency T 10 Threads
  • 176. + Observable<User>  u  =  new  GetUserCommand(id).observe();   Observable<Geo>  g  =  new  GetGeoCommand(request).observe();   ! Observable.zip(u,  g,  {user,  geo  -­‐>                    return  [username:  user.getUsername(),                                    currentLocation:  geo.getCounty()]         }) RxJava in Hystrix 1.3+ https://github.com/Netflix/Hystrix
  • 179. Ben Christensen @benjchristensen http://www.linkedin.com/in/benjchristensen jobs.netflix.com ! Functional Reactive in the Netflix API with RxJava http://techblog.netflix.com/2013/02/rxjava-netflix-api.html ! Optimizing the Netflix API http://techblog.netflix.com/2013/01/optimizing-netflix-api.html ! Application Resilience in a Service-oriented Architecture http://programming.oreilly.com/2013/06/application-resilience-in-a-service-oriented-architecture.html ! Fault Tolerance in a High Volume, Distributed System http://techblog.netflix.com/2012/02/fault-tolerance-in-high-volume.html ! Making the Netflix API More Resilient http://techblog.netflix.com/2011/12/making-netflix-api-more-resilient.html
  • 180. Watch the video with slide synchronization on InfoQ.com! http://www.infoq.com/presentations/netflixapi-evolution