SlideShare ist ein Scribd-Unternehmen logo
1 von 61
Downloaden Sie, um offline zu lesen
Efficient HTTP Apis
A walk through http/2 via okhttp
@adrianfcole
introduction
hello http api!
hello okhttp!
uh oh.. scale!
hello http/2!
wrapping up
introduction
hello http api!
hello okhttp!
uh oh.. scale!
hello http/2!
wrapping up
* Can be blamed for the http/2 defects in okhttp!
@adrianfcole
• engineer at Pivotal on Spring Cloud
• lots of open source work
• focus on cloud computing
okhttp
• HttpURLConnection Apache HttpClient compatible
• designed for java and android
• BDFL: Jesse Wilson from square
https://github.com/square/okhttp
introduction
hello http api!
hello okhttp!
uh oh.. scale!
hello http/2!
wrapping up
$ curl https://apihost/things 
-H ‘SecurityToken: b08c85073c1a2d02’ 
-H ‘Accept: application/json’
[
{
"id": 1,
"owner_id": 0,
"name": "Able"
},
...
{
"id": 26,
"owner_id": 0,
$ curl https://apihost/things/2 
-H ‘SecurityToken: b08c85073c1a2d02’ 
-H ‘Accept: application/json’
{
"id": 2,
"owner_id": 0,
"name": "Beatific"
}
$ curl -X POST https://apihost/things 
-H ‘SecurityToken: b08c85073c1a2d02’ 
-H ‘Content-Type: application/json’ -d
’{
"name": "Open-minded"
}’
$ curl -X DELETE https://apihost/things/2 
-H ‘SecurityToken: b08c85073c1a2d02’
json apis are so simple
$ curl https://apihost/things 
-H ‘SecurityToken: b08c85073c1a2d02’ 
-H ‘Accept: application/json’
[
{
"id": 1,
"owner_id": 0,
"name": "Able"
},
...
{
"id": 26,
"owner_id": 0,
"name": "Zest"
}
$ curl https://apihost/things/2 
-H ‘SecurityToken: b08c85073c1a2d02’ 
-H ‘Accept: application/json’
{
"id": 2,
"owner_id": 0,
"name": "Beatific"
}
$ curl -X POST https://apihost/things 
-H ‘SecurityToken: b08c85073c1a2d02’ 
-H ‘Content-Type: application/json’ -d
’{ "name": "Open-minded" }’
$ curl -X DELETE https://apihost/things/2 
-H ‘SecurityToken: b08c85073c1a2d02’
so many bytes?!
1642!
$ curl --compress https://apihost/things 
-H ‘SecurityToken: b08c85073c1a2d02’ 
-H ‘Accept: application/json’
-H ‘Accept-encoding: gzip, deflate’
[
{
"id": 1,
"owner_id": 0,
"name": "Able"
},
...
{
"id": 26,
"owner_id": 0,
"name": "Zest"
$ curl https://apihost/things/2 
-H ‘SecurityToken: b08c85073c1a2d02’ 
-H ‘Accept: application/json’
{
"id": 2,
"owner_id": 0,
"name": "Beatific"
}
$ curl -X POST https://apihost/things 
-H ‘SecurityToken: b08c85073c1a2d02’ 
-H ‘Content-Type: application/json’ -d
’{ "name": "Open-minded" }’
$ curl -X DELETE https://apihost/things/2 
-H ‘SecurityToken: b08c85073c1a2d02’
now with gzip
318
java + gson
url = new URL(“https://apihost/things”);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty(“SecurityToken”, “b08c85073c1a2d02”);
connection.setRequestProperty(“Accept”, “application/json”);
connection.setRequestProperty(“Accept-Encoding”, "gzip, deflate");
is = connection.getInputStream();
isr = new InputStreamReader(new GZIPInputStream(is));
things = new Gson().fromJson(isr, new TypeToken<List<Thing>>(){});
okhttp + gson
client = new OkHttpClient();
url = new URL(“https://apihost/things”);
connection = new OkUrlFactory(client).open(url);
connection.setRequestProperty(“SecurityToken”, “b08c85073c1a2d02”);
connection.setRequestProperty(“Accept”, “application/json”);
connection.setRequestProperty(“Accept-Encoding”, "gzip, deflate");
is = connection.getInputStream();
isr = new InputStreamReader(is); // automatic gunzip
things = new Gson().fromJson(isr, new TypeToken<List<Thing>>(){});
is.close();
We won!
• List body reduced from 1642 to 318 bytes!
• We saved some lines using OkHttp
• Concession: cpu for compression, curl is a
little verbose.
introduction
hello http api!
hello okhttp!
uh oh.. scale!
hello http/2!
wrapping up
okhttp
• v2.5 has lots of stuff since v1
• buffer, call, cache, interceptor, url
• http/2 and WebSocket support
• Apache adapter
https://github.com/square/okhttp
okhttp
client = new OkHttpClient();
request = new Request.Builder()
.url(“https://apihost/things”)
.header(“SecurityToken”, “b08c85073c1a2d02”)
.header(“Accept”, “application/json”)
.header(“Accept-Encoding”, "gzip, deflate”).build();
// ^^ look, ma.. I’m immutable!
reader = client.newCall(request).execute().body().charStream();
things = new Gson().fromJson(reader, new TypeToken<List<Thing>>(){});
• OkHttp has its own api, which has a
concise way to get bytes or chars
(via okio).
okhttp call
client = new OkHttpClient();
request = new Request.Builder()
.url(“https://apihost/things”)
.header(“SecurityToken”, “b08c85073c1a2d02”)
.header(“Accept”, “application/json”)
.header(“Accept-Encoding”, "gzip, deflate").build();
call = client.newCall(request);
call.enqueue(new ParseThingsCallback());
call.cancel(); // changed my mind
• OkHttp also has an async api,
which (also) supports cancel!
• # Explicity trust certs for your properties
• new CertificatePinner.Builder()
• .add(“my.biz”, publicKeySHA1)
• .add(“*.my.biz”, publicKeySHA1)
• .build()
• # Respond to authentication challenges
• new Authenticator() {
• public Request authenticate(Proxy p, Response rsp) {
• return rsp.request().newBuilder()
• .header(“Authorization", “Bearer …”)
• # Set your own floor for TLS
• new ConnectionSpec.Builder(MODERN_TLS)
okhttp
security
okhttp interceptor
client = new OkHttpClient();
client.interceptors().add((chain) ->

chain.proceed(chain.request().newBuilder()

.addHeader("SecurityToken", securityToken.get())

.build())

);
request = new Request.Builder()
.url(“https://apihost/things”)
.header(“Accept-Encoding”, "gzip, deflate").build();
call = client.newCall(request);
call.enqueue(new ParseThingsCallback());
• Now you can change your
security token!
okio
• ByteString
• Unbounded Buffer
• Source/Sink abstraction
https://github.com/square/okio
// Okio is (more than) a prettier DataInputStream
BufferedSink sink = Okio.buffer(Okio.sink(file));
sink.writeUtf8("Hello, java.io file!”);
sink.writeLong(1000000000000000L);
sink.close();
// Streaming writes with no housekeeping
new RequestBody() {
@Override public void writeTo(BufferedSink sink) throws IOException {
sink.writeUtf8("Numbersn");
sink.writeUtf8("-------n");
for (int i = 2; i <= 997; i++) {
sink.writeUtf8(String.format(" * %s = %sn", i, factor(i)));
}
}
—snip—
// Lazy, composable bodies
new MultipartBuilder("123")
.addPart(RequestBody.create(MediaType.parse(“text/plain”, "Quick"))
.addPart(new StreamingBody("Brown"))
okio
samples
samples
• Starters like web crawler
• How-to guide w/ recipes
https://github.com/square/okhttp/tree/master/samples
introduction
hello http api!
hello okhttp!
uh oh.. scale!
hello http/2!
wrapping up
Hey.. List #1 is slow!
368!
Ask Ilya why!
• TCP connections need 3-
way handshake.
• TLS requires up to 2
more round-trips.
• Read High Performance
Browser Networking
http://chimera.labs.oreilly.com/books/1230000000545
HttpUrlConnection
• http.keepAlive - should connections should be
pooled at all? Default is true.
• http.maxConnections - maximum number of idle
connections to each host in the pool. Default is 5.
• get[Input|Error]Stream().close() - recycles the
connection, if fully read.
• disconnect() - removes the connection.
Don’t forget to read!
...
is = tryGetInputStream(connection);
isr = new InputStreamReader(is);
things = new Gson().fromJson(isr, new TypeToken<List<Thing>>(){});
...
InputStream tryGetInputStream(HttpUrlConnection connection) throws IOException {
try {
return connection.getInputStream();
} catch (IOException e) {
InputStream err = connection.getErrorStream();
  while (in.read() != -1); // skip
err.close();
throw e;
}
or just use okhttp
try (ResponseBody body = client.newCall(request).execute().body())
{
// connection will be cleaned on close.
}
client.newCall(request).enqueue(new Callback() {
@Override public void onFailure(Request request, IOException e) {
// body is implicitly closed on failure
}
@Override public void onResponse(Response response) {
// make sure you call response.body().close() when done
}
});
We won!
• Recycled socket requests are much faster
and have less impact on the server.
• Concessions: must read responses,
concurrency is still bounded by sockets.
Let’s make List #2 free
Cache-Control: private, max-age=60, s-maxage=0
Vary: SecurityToken
Step 1: add a little magic to your server response
Step 2: make sure you are using a cache!
client.setCache(new Cache(dir, 10_MB));
Step 3: pray your developers don’t get clever
// TODO: stupid server sends stale data without this
new Request.Builder().url(”https://apihost/things?time=” + currentTimeMillis());
// Limit cache duration
thisMessageWillSelfDestruct = new Request.Builder()
.url(“https://foo.com/weather”)
.cacheControl(new CacheControl.Builder().maxAge(12, HOURS).build())
.build();
// Opt-out of response caching
notStored = new Request.Builder()
.url(“https://foo.com/private”)
.cacheControl(CacheControl.FORCE_NETWORK)
.build();
// Offline mode
offline = new Request.Builder()
.url(“https://foo.com/image”)
.cacheControl(CacheControl.FORCE_CACHE)
.build();
okhttp cache recipes
We won again!
• No time or bandwidth used for cached
responses
• No application-specific cache bugs code.
• Concessions: only supports “safe methods”,
caching needs to be tuned.
introduction
hello http api!
hello okhttp!
uh oh.. scale!
hello http/2!
wrapping up
http/1.1
• rfc2616 - June 1999
• text-based framing
• defined semantics of the web
http://www.w3.org/Protocols/rfc2616/rfc2616.html
FYI: RFC 2616 is dead!
• RFC 7230-5 replaces RFC 2616.
• Checkout details on www.mnot.net/blog
spdy/3.1
http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1
• google - Sep 2013
• binary framing
• retains http/1.1 semantics
• concurrent multiplexed streams
http/2
https://tools.ietf.org/html/rfc7540
• rfc7540 - May 2015
• binary framing
• retains http/1.1 semantics
• concurrent multiplexed streams
multiplexing
header compression
flow control
priority
server push
http/2 headline features
multiplexing
header compression
server push
http/2 headline features
Looking at the whole
message
Request: request line, headers, and body
Response: status line, headers, and body
http/1.1 round-trip
GZIPPED DATA
Content-Length: 318
Cache-Control: private, max-age=60, s-
maxage=0
Vary: SecurityToken
Date: Sun, 02 Feb 2014 20:30:38 GMT
Content-Type: application/json
Content-Encoding: gzip
Host: apihost
SecurityToken: b08c85073c1a2d02
Accept: application/json
Accept-encoding: gzip, deflate
GET /things HTTP/1.1
HTTP/1.1 200 OK
• http/1.1 sends requests and
responses one at a time
over a network connection
http/2 round-trip
GZIPPED DATA
:status: 200
content-length: 318
cache-control: private, max-age=60, s-
maxage=0
vary: SecurityToken
date: Sun, 02 Feb 2014 20:30:38 GMT
content-type: application/json
:method: GET
:authority: apihost
:path: /things
securitytoken: b08c85073c1a2d02
accept: application/json
accept-encoding: gzip, deflate
HEADERS
Stream: 3
Flags: END_HEADERS, END_STREAM
HEADERS
Stream: 3
Flags: END_HEADERS
DATA
Stream: 3
Flags: END_STREAM
• http/2 breaks up messages
into stream-scoped frames
Interleaving
HEADERS
Stream: 5
Flags: END_HEADERS, END_STREAM
HEADERS
Stream: 3
Flags: END_HEADERS
DATA
Stream: 5
Flags:
DATA
Stream: 5
Flags: END_STREAM
HEADERS
Stream: 3
Flags: END_HEADERS, END_STREAM
HEADERS
Stream: 5
Flags: END_HEADERS
DATA
Stream: 3
Flags: END_STREAM
• http/2 multiplexes a network
connection by interleaving
request/response frames
Canceling a Stream
HEADERS
Stream: 5
Flags: END_HEADERS, END_STREAM
HEADERS
Stream: 3
Flags: END_HEADERS
DATA
Stream: 5
Flags:
HEADERS
Stream: 3
Flags: END_HEADERS, END_STREAM
HEADERS
Stream: 5
Flags: END_HEADERS
DATA
Stream: 3
Flags: END_STREAM
RST_STREAM
Stream: 5
ErrorCode: CANCEL
• interrupts a response without
affecting the connection
control frames
HEADERS
Stream: 5
HEADERS
Stream: 3
DATA
Stream: 5
DATA
Stream: 3
HEADERS
Stream: 3
HEADERS
Stream: 5
SETTINGS
Stream: 0
SETTINGS
Stream: 0
DATA
Stream: 5
• connection-scoped frames
allow runtime updates, like
flow-control
OkHttp/2 Architecture
Frame
Reader
Thread
Frame
Writer
Lock
Control
Frame
Queue
FramedConnection
multiplexing
header compression
server push
http/2 headline features
http/1.1 headers
GZIPPED DATA
Content-Length: 318
Cache-Control: private, max-age=60, s-
maxage=0
Vary: SecurityToken
Date: Sun, 02 Feb 2014 20:30:38 GMT
Content-Type: application/json
Content-Encoding: gzip
Host: apihost
SecurityToken: b08c85073c1a2d02
Accept: application/json
Accept-encoding: gzip, deflate
GET /things HTTP/1.1
HTTP/1.1 200 OK
168!
195!
318
• You can gzip
data, but not
headers!
header compression
GZIPPED DATA
:status: 200
content-length: 318
cache-control: private, max-age=60, s-maxage=0
vary: SecurityToken
date: Sun, 02 Feb 2014 20:30:38 GMT
content-type: application/json
content-encoding: gzip
:method: GET
:authority: apihost
:path: /things
securitytoken: b08c85073c1a2d02
accept: application/json
accept-encoding: gzip, deflate
HEADERS
Stream: 3
Flags: END_HEADERS, END_STREAM
HEADERS
Stream: 3
Flags: END_HEADERS
DATA
Stream: 3
Flags: END_STREAM
8 bytes
52 bytes compressed
8 bytes
85 bytes compressed
• 161 byte overhead
instead of 363 8 bytes
indexed headers!
GZIPPED DATA
:status: 200
content-length: 318
cache-control: private, max-age=60, s-maxage=0
vary: SecurityToken
date: Sun, 02 Feb 2014 20:30:39 GMT
content-type: application/json
content-encoding: gzip
:method: GET
:authority: apihost
:path: /things
securitytoken: b08c85073c1a2d02
accept: application/json
accept-encoding: gzip, deflate
HEADERS
Stream: 3
Flags: END_HEADERS, END_STREAM
HEADERS
Stream: 3
Flags: END_HEADERS
DATA
Stream: 3
Flags: END_STREAM
8 bytes
28 bytes compressed
8 bytes
30 bytes compressed
• 82 byte overhead
instead of 363 8 bytes
hpack
http://tools.ietf.org/html/rfc7541
• rfc7540 - May 2015
• static and dynamic table
• huffman encoding
multiplexing
header compression
server push
http/2 headline features
push promise
:method: GET
:path: /things
...
HEADERS
Stream: 3
HEADERS
Stream: 3
DATA
Stream: 4
:method: GET
:path: /users/0
...
PUSH_PROMISE
Stream: 3
Promised-Stream: 4
HEADERS
Stream: 4
push
response
goes into
cache
DATA
Stream: 3
Server guesses a
future request or
indicates a cache
invalidation
okhttp + http/2
• OkHttp 2.3+ supports http/2 on TLS+ALPN connections.
• Works out of the box on Android
• Java needs hacks until JEP 244
For now, add jetty’s ALPN to your bootclasspath.
* Verify version matches your JRE *
$ java -Xbootclasspath/p:/path/to/alpn-boot-8.1.4.v20150727.jar
We won!
• 1 socket for 100+ concurrent streams.
• Advanced features like flow control,
cancellation and cache push.
• Dramatically less header overhead.
okhttp tools
• There are tools that leverage OkHttp natively…
• including its http/2 features.
MockWebServer
SSLSocketFactory factory = SslContextBuilder.localhost().getSocketFactory();
OkHttpClient client = new OkHttpClient()
.setSslSocketFactory(factory);
@Rule public final MockWebServer server = new MockWebServer()
.setSslSocketFactory(factory);
@Test public void evenWithHttp2SlowResponsesKill() throws Exception {
server.enqueue(new MockResponse().setBody(lotsOfThings)
.throttleBody(1024, 1, SECONDS)); // slow connection 1KiB/second
request = new Request.Builder()
.url(server.getUrl(”/”) + ”things”)
—snip—
• MockWebServer uses http/2
by default when using TLS
Retrofit 2
@Headers("Accept-Encoding: gzip, deflate”)
interface ThingService {
@GET("things") Single<List<Things> list(); // RxJava support!
}
retrofit = new Retrofit.Builder()
.client(client)
.baseUrl(“https://apihost/“)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
thingsService = retrofit.create(ThingService.class);
subscription = thingsService.iist().subscribe(System.out::println)
• Retrofit 2 extends OkHttp
with api model binding
okcurl
$ java -Xbootclasspath/p:alpn-boot.jar -jar okcurl.jar https://twitter.com
-X HEAD --frames
>> CONNECTION 505249202a20485454502f322e300d0a0d0a534d0d0a0d0a
<< 0x00000000 6 SETTINGS
>> 0x00000000 6 SETTINGS
>> 0x00000000 4 WINDOW_UPDATE
>> 0x00000000 0 SETTINGS ACK
>> 0x00000003 60 HEADERS END_STREAM|END_HEADERS
<< 0x00000000 0 SETTINGS ACK
<< 0x00000003 2097 HEADERS END_STREAM|END_HEADERS
>> 0x00000000 8 GOAWAY
introduction
hello http api!
hello okhttp!
uh oh.. scale!
hello http/2!
wrapping up
Engage!
• Consider http/2 or at least spdy!
• Check-out okhttp and friends
• Test http/2 load balancers like google cloud
https://github.com/square/okhttp/tree/master/mockwebserver
http://square.github.io/retrofit/
https://cloud.google.com/compute/docs/load-balancing/http/
Thank you!
github square/okhttp @adrianfcole

Weitere ähnliche Inhalte

Was ist angesagt?

HTTP/2 Introduction
HTTP/2 IntroductionHTTP/2 Introduction
HTTP/2 IntroductionWalter Liu
 
Altitude San Francisco 2018: Programming the Edge
Altitude San Francisco 2018: Programming the EdgeAltitude San Francisco 2018: Programming the Edge
Altitude San Francisco 2018: Programming the EdgeFastly
 
HTTP2:新的机遇与挑战
HTTP2:新的机遇与挑战HTTP2:新的机遇与挑战
HTTP2:新的机遇与挑战Jerry Qu
 
Introduction to HTTP/2
Introduction to HTTP/2Introduction to HTTP/2
Introduction to HTTP/2Ido Flatow
 
Revisiting HTTP/2
Revisiting HTTP/2Revisiting HTTP/2
Revisiting HTTP/2Fastly
 
HTTP/2 Update - FOSDEM 2016
HTTP/2 Update - FOSDEM 2016HTTP/2 Update - FOSDEM 2016
HTTP/2 Update - FOSDEM 2016Daniel Stenberg
 
Altitude San Francisco 2018: Testing with Fastly Workshop
Altitude San Francisco 2018: Testing with Fastly WorkshopAltitude San Francisco 2018: Testing with Fastly Workshop
Altitude San Francisco 2018: Testing with Fastly WorkshopFastly
 
HTTP 2.0 Why, How and When
HTTP 2.0 Why, How and WhenHTTP 2.0 Why, How and When
HTTP 2.0 Why, How and WhenCodemotion
 
So that was HTTP/2, what's next?
So that was HTTP/2, what's next?So that was HTTP/2, what's next?
So that was HTTP/2, what's next?Daniel Stenberg
 
HTTP2 & HPACK #pyfes 2013-11-30
HTTP2 & HPACK #pyfes 2013-11-30HTTP2 & HPACK #pyfes 2013-11-30
HTTP2 & HPACK #pyfes 2013-11-30Jxck Jxck
 
Covert Timing Channels using HTTP Cache Headers
Covert Timing Channels using HTTP Cache HeadersCovert Timing Channels using HTTP Cache Headers
Covert Timing Channels using HTTP Cache HeadersDenis Kolegov
 
Introducing HTTP/2
Introducing HTTP/2Introducing HTTP/2
Introducing HTTP/2Ido Flatow
 
5 steps to faster web sites & HTML5 games - updated for DDDscot
5 steps to faster web sites & HTML5 games - updated for DDDscot5 steps to faster web sites & HTML5 games - updated for DDDscot
5 steps to faster web sites & HTML5 games - updated for DDDscotMichael Ewins
 
HTTP 2.0 – What do I need to know?
HTTP 2.0 – What do I need to know? HTTP 2.0 – What do I need to know?
HTTP 2.0 – What do I need to know? Sigma Software
 

Was ist angesagt? (20)

Just curl it!
Just curl it!Just curl it!
Just curl it!
 
HTTP2 is Here!
HTTP2 is Here!HTTP2 is Here!
HTTP2 is Here!
 
HTTP/2 Introduction
HTTP/2 IntroductionHTTP/2 Introduction
HTTP/2 Introduction
 
Altitude San Francisco 2018: Programming the Edge
Altitude San Francisco 2018: Programming the EdgeAltitude San Francisco 2018: Programming the Edge
Altitude San Francisco 2018: Programming the Edge
 
HTTP2:新的机遇与挑战
HTTP2:新的机遇与挑战HTTP2:新的机遇与挑战
HTTP2:新的机遇与挑战
 
Introduction to HTTP/2
Introduction to HTTP/2Introduction to HTTP/2
Introduction to HTTP/2
 
Revisiting HTTP/2
Revisiting HTTP/2Revisiting HTTP/2
Revisiting HTTP/2
 
HTTP/2 Update - FOSDEM 2016
HTTP/2 Update - FOSDEM 2016HTTP/2 Update - FOSDEM 2016
HTTP/2 Update - FOSDEM 2016
 
Altitude San Francisco 2018: Testing with Fastly Workshop
Altitude San Francisco 2018: Testing with Fastly WorkshopAltitude San Francisco 2018: Testing with Fastly Workshop
Altitude San Francisco 2018: Testing with Fastly Workshop
 
Http2 right now
Http2 right nowHttp2 right now
Http2 right now
 
ZN27112015
ZN27112015ZN27112015
ZN27112015
 
HTTP 2.0 Why, How and When
HTTP 2.0 Why, How and WhenHTTP 2.0 Why, How and When
HTTP 2.0 Why, How and When
 
So that was HTTP/2, what's next?
So that was HTTP/2, what's next?So that was HTTP/2, what's next?
So that was HTTP/2, what's next?
 
HTTP2 & HPACK #pyfes 2013-11-30
HTTP2 & HPACK #pyfes 2013-11-30HTTP2 & HPACK #pyfes 2013-11-30
HTTP2 & HPACK #pyfes 2013-11-30
 
Covert Timing Channels using HTTP Cache Headers
Covert Timing Channels using HTTP Cache HeadersCovert Timing Channels using HTTP Cache Headers
Covert Timing Channels using HTTP Cache Headers
 
curl better
curl bettercurl better
curl better
 
HTTP/3
HTTP/3HTTP/3
HTTP/3
 
Introducing HTTP/2
Introducing HTTP/2Introducing HTTP/2
Introducing HTTP/2
 
5 steps to faster web sites & HTML5 games - updated for DDDscot
5 steps to faster web sites & HTML5 games - updated for DDDscot5 steps to faster web sites & HTML5 games - updated for DDDscot
5 steps to faster web sites & HTML5 games - updated for DDDscot
 
HTTP 2.0 – What do I need to know?
HTTP 2.0 – What do I need to know? HTTP 2.0 – What do I need to know?
HTTP 2.0 – What do I need to know?
 

Andere mochten auch

Chicago Hadoop Users Group: Enterprise Data Workflows
Chicago Hadoop Users Group: Enterprise Data WorkflowsChicago Hadoop Users Group: Enterprise Data Workflows
Chicago Hadoop Users Group: Enterprise Data WorkflowsPaco Nathan
 
Spring 3.1 and MVC Testing Support - 4Developers
Spring 3.1 and MVC Testing Support - 4DevelopersSpring 3.1 and MVC Testing Support - 4Developers
Spring 3.1 and MVC Testing Support - 4DevelopersSam Brannen
 
Reactive Programming With Akka - Lessons Learned
Reactive Programming With Akka - Lessons LearnedReactive Programming With Akka - Lessons Learned
Reactive Programming With Akka - Lessons LearnedDaniel Sawano
 
A Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingA Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingGarth Gilmour
 
The no-framework Scala Dependency Injection Framework
The no-framework Scala Dependency Injection FrameworkThe no-framework Scala Dependency Injection Framework
The no-framework Scala Dependency Injection FrameworkAdam Warski
 
Actor Based Asyncronous IO in Akka
Actor Based Asyncronous IO in AkkaActor Based Asyncronous IO in Akka
Actor Based Asyncronous IO in Akkadrewhk
 
Effective akka scalaio
Effective akka scalaioEffective akka scalaio
Effective akka scalaioshinolajla
 
Beginning Haskell, Dive In, Its Not That Scary!
Beginning Haskell, Dive In, Its Not That Scary!Beginning Haskell, Dive In, Its Not That Scary!
Beginning Haskell, Dive In, Its Not That Scary!priort
 
C*ollege Credit: Creating Your First App in Java with Cassandra
C*ollege Credit: Creating Your First App in Java with CassandraC*ollege Credit: Creating Your First App in Java with Cassandra
C*ollege Credit: Creating Your First App in Java with CassandraDataStax
 
Building ‘Bootiful’ microservices cloud
Building ‘Bootiful’ microservices cloudBuilding ‘Bootiful’ microservices cloud
Building ‘Bootiful’ microservices cloudIdan Fridman
 
Effective Actors
Effective ActorsEffective Actors
Effective Actorsshinolajla
 
Using Apache Solr
Using Apache SolrUsing Apache Solr
Using Apache Solrpittaya
 
Effective Scala (SoftShake 2013)
Effective Scala (SoftShake 2013)Effective Scala (SoftShake 2013)
Effective Scala (SoftShake 2013)mircodotta
 
Composable and streamable Play apps
Composable and streamable Play appsComposable and streamable Play apps
Composable and streamable Play appsYevgeniy Brikman
 
Clean Architecture
Clean ArchitectureClean Architecture
Clean ArchitectureBadoo
 
Introducing Clean Architecture
Introducing Clean ArchitectureIntroducing Clean Architecture
Introducing Clean ArchitectureRoc Boronat
 
An example of Future composition in a real app
An example of Future composition in a real appAn example of Future composition in a real app
An example of Future composition in a real appPhil Calçado
 
Clean architecture
Clean architectureClean architecture
Clean architectureandbed
 
Design for developers
Design for developersDesign for developers
Design for developersJohan Ronsse
 

Andere mochten auch (20)

Chicago Hadoop Users Group: Enterprise Data Workflows
Chicago Hadoop Users Group: Enterprise Data WorkflowsChicago Hadoop Users Group: Enterprise Data Workflows
Chicago Hadoop Users Group: Enterprise Data Workflows
 
Spring 3.1 and MVC Testing Support - 4Developers
Spring 3.1 and MVC Testing Support - 4DevelopersSpring 3.1 and MVC Testing Support - 4Developers
Spring 3.1 and MVC Testing Support - 4Developers
 
Reactive Programming With Akka - Lessons Learned
Reactive Programming With Akka - Lessons LearnedReactive Programming With Akka - Lessons Learned
Reactive Programming With Akka - Lessons Learned
 
A Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingA Sceptical Guide to Functional Programming
A Sceptical Guide to Functional Programming
 
The no-framework Scala Dependency Injection Framework
The no-framework Scala Dependency Injection FrameworkThe no-framework Scala Dependency Injection Framework
The no-framework Scala Dependency Injection Framework
 
Actor Based Asyncronous IO in Akka
Actor Based Asyncronous IO in AkkaActor Based Asyncronous IO in Akka
Actor Based Asyncronous IO in Akka
 
Effective akka scalaio
Effective akka scalaioEffective akka scalaio
Effective akka scalaio
 
Beginning Haskell, Dive In, Its Not That Scary!
Beginning Haskell, Dive In, Its Not That Scary!Beginning Haskell, Dive In, Its Not That Scary!
Beginning Haskell, Dive In, Its Not That Scary!
 
C*ollege Credit: Creating Your First App in Java with Cassandra
C*ollege Credit: Creating Your First App in Java with CassandraC*ollege Credit: Creating Your First App in Java with Cassandra
C*ollege Credit: Creating Your First App in Java with Cassandra
 
Building ‘Bootiful’ microservices cloud
Building ‘Bootiful’ microservices cloudBuilding ‘Bootiful’ microservices cloud
Building ‘Bootiful’ microservices cloud
 
Effective Actors
Effective ActorsEffective Actors
Effective Actors
 
Curator intro
Curator introCurator intro
Curator intro
 
Using Apache Solr
Using Apache SolrUsing Apache Solr
Using Apache Solr
 
Effective Scala (SoftShake 2013)
Effective Scala (SoftShake 2013)Effective Scala (SoftShake 2013)
Effective Scala (SoftShake 2013)
 
Composable and streamable Play apps
Composable and streamable Play appsComposable and streamable Play apps
Composable and streamable Play apps
 
Clean Architecture
Clean ArchitectureClean Architecture
Clean Architecture
 
Introducing Clean Architecture
Introducing Clean ArchitectureIntroducing Clean Architecture
Introducing Clean Architecture
 
An example of Future composition in a real app
An example of Future composition in a real appAn example of Future composition in a real app
An example of Future composition in a real app
 
Clean architecture
Clean architectureClean architecture
Clean architecture
 
Design for developers
Design for developersDesign for developers
Design for developers
 

Ähnlich wie Efficient HTTP APIs with OkHttp

10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 202010 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020Matt Raible
 
OpenStack APIs: Present and Future (Beta Talk)
OpenStack APIs: Present and Future (Beta Talk)OpenStack APIs: Present and Future (Beta Talk)
OpenStack APIs: Present and Future (Beta Talk)Wade Minter
 
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 201910 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019Matt Raible
 
Solving anything in VCL
Solving anything in VCLSolving anything in VCL
Solving anything in VCLFastly
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaFrank Lyaruu
 
REST with Eve and Python
REST with Eve and PythonREST with Eve and Python
REST with Eve and PythonPiXeL16
 
Apache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestApache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestMyles Braithwaite
 
Android httpclient
Android httpclientAndroid httpclient
Android httpclientallanh0526
 
Nordic APIs - Automatic Testing of (RESTful) API Documentation
Nordic APIs - Automatic Testing of (RESTful) API DocumentationNordic APIs - Automatic Testing of (RESTful) API Documentation
Nordic APIs - Automatic Testing of (RESTful) API DocumentationRouven Weßling
 
Rpi python web
Rpi python webRpi python web
Rpi python websewoo lee
 
Intro to fog and openstack jp
Intro to fog and openstack jpIntro to fog and openstack jp
Intro to fog and openstack jpSatoshi Konno
 
Build resource server &amp; client for OCF Cloud (2018.8.30)
Build resource server &amp; client for OCF Cloud (2018.8.30)Build resource server &amp; client for OCF Cloud (2018.8.30)
Build resource server &amp; client for OCF Cloud (2018.8.30)남균 김
 
Service Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and KubernetesService Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and KubernetesSreenivas Makam
 
OpenStack API's and WSGI
OpenStack API's and WSGIOpenStack API's and WSGI
OpenStack API's and WSGIMike Pittaro
 
how to use openstack api
how to use openstack apihow to use openstack api
how to use openstack apiLiang Bo
 

Ähnlich wie Efficient HTTP APIs with OkHttp (20)

10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 202010 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
 
OpenStack APIs: Present and Future (Beta Talk)
OpenStack APIs: Present and Future (Beta Talk)OpenStack APIs: Present and Future (Beta Talk)
OpenStack APIs: Present and Future (Beta Talk)
 
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 201910 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
Solving anything in VCL
Solving anything in VCLSolving anything in VCL
Solving anything in VCL
 
Server Side Swift: Vapor
Server Side Swift: VaporServer Side Swift: Vapor
Server Side Swift: Vapor
 
Caching. api. http 1.1
Caching. api. http 1.1Caching. api. http 1.1
Caching. api. http 1.1
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJava
 
REST with Eve and Python
REST with Eve and PythonREST with Eve and Python
REST with Eve and Python
 
Apache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestApache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux Fest
 
Android httpclient
Android httpclientAndroid httpclient
Android httpclient
 
Nordic APIs - Automatic Testing of (RESTful) API Documentation
Nordic APIs - Automatic Testing of (RESTful) API DocumentationNordic APIs - Automatic Testing of (RESTful) API Documentation
Nordic APIs - Automatic Testing of (RESTful) API Documentation
 
Socket.IO
Socket.IOSocket.IO
Socket.IO
 
Rpi python web
Rpi python webRpi python web
Rpi python web
 
Intro to fog and openstack jp
Intro to fog and openstack jpIntro to fog and openstack jp
Intro to fog and openstack jp
 
Introduction to Traefik
Introduction to TraefikIntroduction to Traefik
Introduction to Traefik
 
Build resource server &amp; client for OCF Cloud (2018.8.30)
Build resource server &amp; client for OCF Cloud (2018.8.30)Build resource server &amp; client for OCF Cloud (2018.8.30)
Build resource server &amp; client for OCF Cloud (2018.8.30)
 
Service Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and KubernetesService Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and Kubernetes
 
OpenStack API's and WSGI
OpenStack API's and WSGIOpenStack API's and WSGI
OpenStack API's and WSGI
 
how to use openstack api
how to use openstack apihow to use openstack api
how to use openstack api
 

Kürzlich hochgeladen

Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 

Kürzlich hochgeladen (20)

Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 

Efficient HTTP APIs with OkHttp

  • 1. Efficient HTTP Apis A walk through http/2 via okhttp @adrianfcole
  • 2. introduction hello http api! hello okhttp! uh oh.. scale! hello http/2! wrapping up
  • 3. introduction hello http api! hello okhttp! uh oh.. scale! hello http/2! wrapping up
  • 4. * Can be blamed for the http/2 defects in okhttp! @adrianfcole • engineer at Pivotal on Spring Cloud • lots of open source work • focus on cloud computing
  • 5. okhttp • HttpURLConnection Apache HttpClient compatible • designed for java and android • BDFL: Jesse Wilson from square https://github.com/square/okhttp
  • 6. introduction hello http api! hello okhttp! uh oh.. scale! hello http/2! wrapping up
  • 7. $ curl https://apihost/things -H ‘SecurityToken: b08c85073c1a2d02’ -H ‘Accept: application/json’ [ { "id": 1, "owner_id": 0, "name": "Able" }, ... { "id": 26, "owner_id": 0, $ curl https://apihost/things/2 -H ‘SecurityToken: b08c85073c1a2d02’ -H ‘Accept: application/json’ { "id": 2, "owner_id": 0, "name": "Beatific" } $ curl -X POST https://apihost/things -H ‘SecurityToken: b08c85073c1a2d02’ -H ‘Content-Type: application/json’ -d ’{ "name": "Open-minded" }’ $ curl -X DELETE https://apihost/things/2 -H ‘SecurityToken: b08c85073c1a2d02’ json apis are so simple
  • 8. $ curl https://apihost/things -H ‘SecurityToken: b08c85073c1a2d02’ -H ‘Accept: application/json’ [ { "id": 1, "owner_id": 0, "name": "Able" }, ... { "id": 26, "owner_id": 0, "name": "Zest" } $ curl https://apihost/things/2 -H ‘SecurityToken: b08c85073c1a2d02’ -H ‘Accept: application/json’ { "id": 2, "owner_id": 0, "name": "Beatific" } $ curl -X POST https://apihost/things -H ‘SecurityToken: b08c85073c1a2d02’ -H ‘Content-Type: application/json’ -d ’{ "name": "Open-minded" }’ $ curl -X DELETE https://apihost/things/2 -H ‘SecurityToken: b08c85073c1a2d02’ so many bytes?! 1642!
  • 9. $ curl --compress https://apihost/things -H ‘SecurityToken: b08c85073c1a2d02’ -H ‘Accept: application/json’ -H ‘Accept-encoding: gzip, deflate’ [ { "id": 1, "owner_id": 0, "name": "Able" }, ... { "id": 26, "owner_id": 0, "name": "Zest" $ curl https://apihost/things/2 -H ‘SecurityToken: b08c85073c1a2d02’ -H ‘Accept: application/json’ { "id": 2, "owner_id": 0, "name": "Beatific" } $ curl -X POST https://apihost/things -H ‘SecurityToken: b08c85073c1a2d02’ -H ‘Content-Type: application/json’ -d ’{ "name": "Open-minded" }’ $ curl -X DELETE https://apihost/things/2 -H ‘SecurityToken: b08c85073c1a2d02’ now with gzip 318
  • 10. java + gson url = new URL(“https://apihost/things”); connection = (HttpURLConnection) url.openConnection(); connection.setRequestProperty(“SecurityToken”, “b08c85073c1a2d02”); connection.setRequestProperty(“Accept”, “application/json”); connection.setRequestProperty(“Accept-Encoding”, "gzip, deflate"); is = connection.getInputStream(); isr = new InputStreamReader(new GZIPInputStream(is)); things = new Gson().fromJson(isr, new TypeToken<List<Thing>>(){});
  • 11. okhttp + gson client = new OkHttpClient(); url = new URL(“https://apihost/things”); connection = new OkUrlFactory(client).open(url); connection.setRequestProperty(“SecurityToken”, “b08c85073c1a2d02”); connection.setRequestProperty(“Accept”, “application/json”); connection.setRequestProperty(“Accept-Encoding”, "gzip, deflate"); is = connection.getInputStream(); isr = new InputStreamReader(is); // automatic gunzip things = new Gson().fromJson(isr, new TypeToken<List<Thing>>(){}); is.close();
  • 12. We won! • List body reduced from 1642 to 318 bytes! • We saved some lines using OkHttp • Concession: cpu for compression, curl is a little verbose.
  • 13. introduction hello http api! hello okhttp! uh oh.. scale! hello http/2! wrapping up
  • 14. okhttp • v2.5 has lots of stuff since v1 • buffer, call, cache, interceptor, url • http/2 and WebSocket support • Apache adapter https://github.com/square/okhttp
  • 15. okhttp client = new OkHttpClient(); request = new Request.Builder() .url(“https://apihost/things”) .header(“SecurityToken”, “b08c85073c1a2d02”) .header(“Accept”, “application/json”) .header(“Accept-Encoding”, "gzip, deflate”).build(); // ^^ look, ma.. I’m immutable! reader = client.newCall(request).execute().body().charStream(); things = new Gson().fromJson(reader, new TypeToken<List<Thing>>(){}); • OkHttp has its own api, which has a concise way to get bytes or chars (via okio).
  • 16. okhttp call client = new OkHttpClient(); request = new Request.Builder() .url(“https://apihost/things”) .header(“SecurityToken”, “b08c85073c1a2d02”) .header(“Accept”, “application/json”) .header(“Accept-Encoding”, "gzip, deflate").build(); call = client.newCall(request); call.enqueue(new ParseThingsCallback()); call.cancel(); // changed my mind • OkHttp also has an async api, which (also) supports cancel!
  • 17. • # Explicity trust certs for your properties • new CertificatePinner.Builder() • .add(“my.biz”, publicKeySHA1) • .add(“*.my.biz”, publicKeySHA1) • .build() • # Respond to authentication challenges • new Authenticator() { • public Request authenticate(Proxy p, Response rsp) { • return rsp.request().newBuilder() • .header(“Authorization", “Bearer …”) • # Set your own floor for TLS • new ConnectionSpec.Builder(MODERN_TLS) okhttp security
  • 18. okhttp interceptor client = new OkHttpClient(); client.interceptors().add((chain) ->
 chain.proceed(chain.request().newBuilder()
 .addHeader("SecurityToken", securityToken.get())
 .build())
 ); request = new Request.Builder() .url(“https://apihost/things”) .header(“Accept-Encoding”, "gzip, deflate").build(); call = client.newCall(request); call.enqueue(new ParseThingsCallback()); • Now you can change your security token!
  • 19. okio • ByteString • Unbounded Buffer • Source/Sink abstraction https://github.com/square/okio
  • 20. // Okio is (more than) a prettier DataInputStream BufferedSink sink = Okio.buffer(Okio.sink(file)); sink.writeUtf8("Hello, java.io file!”); sink.writeLong(1000000000000000L); sink.close(); // Streaming writes with no housekeeping new RequestBody() { @Override public void writeTo(BufferedSink sink) throws IOException { sink.writeUtf8("Numbersn"); sink.writeUtf8("-------n"); for (int i = 2; i <= 997; i++) { sink.writeUtf8(String.format(" * %s = %sn", i, factor(i))); } } —snip— // Lazy, composable bodies new MultipartBuilder("123") .addPart(RequestBody.create(MediaType.parse(“text/plain”, "Quick")) .addPart(new StreamingBody("Brown")) okio samples
  • 21. samples • Starters like web crawler • How-to guide w/ recipes https://github.com/square/okhttp/tree/master/samples
  • 22. introduction hello http api! hello okhttp! uh oh.. scale! hello http/2! wrapping up
  • 23. Hey.. List #1 is slow! 368!
  • 24. Ask Ilya why! • TCP connections need 3- way handshake. • TLS requires up to 2 more round-trips. • Read High Performance Browser Networking http://chimera.labs.oreilly.com/books/1230000000545
  • 25. HttpUrlConnection • http.keepAlive - should connections should be pooled at all? Default is true. • http.maxConnections - maximum number of idle connections to each host in the pool. Default is 5. • get[Input|Error]Stream().close() - recycles the connection, if fully read. • disconnect() - removes the connection.
  • 26. Don’t forget to read! ... is = tryGetInputStream(connection); isr = new InputStreamReader(is); things = new Gson().fromJson(isr, new TypeToken<List<Thing>>(){}); ... InputStream tryGetInputStream(HttpUrlConnection connection) throws IOException { try { return connection.getInputStream(); } catch (IOException e) { InputStream err = connection.getErrorStream();   while (in.read() != -1); // skip err.close(); throw e; }
  • 27. or just use okhttp try (ResponseBody body = client.newCall(request).execute().body()) { // connection will be cleaned on close. } client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Request request, IOException e) { // body is implicitly closed on failure } @Override public void onResponse(Response response) { // make sure you call response.body().close() when done } });
  • 28. We won! • Recycled socket requests are much faster and have less impact on the server. • Concessions: must read responses, concurrency is still bounded by sockets.
  • 29. Let’s make List #2 free Cache-Control: private, max-age=60, s-maxage=0 Vary: SecurityToken Step 1: add a little magic to your server response Step 2: make sure you are using a cache! client.setCache(new Cache(dir, 10_MB)); Step 3: pray your developers don’t get clever // TODO: stupid server sends stale data without this new Request.Builder().url(”https://apihost/things?time=” + currentTimeMillis());
  • 30. // Limit cache duration thisMessageWillSelfDestruct = new Request.Builder() .url(“https://foo.com/weather”) .cacheControl(new CacheControl.Builder().maxAge(12, HOURS).build()) .build(); // Opt-out of response caching notStored = new Request.Builder() .url(“https://foo.com/private”) .cacheControl(CacheControl.FORCE_NETWORK) .build(); // Offline mode offline = new Request.Builder() .url(“https://foo.com/image”) .cacheControl(CacheControl.FORCE_CACHE) .build(); okhttp cache recipes
  • 31. We won again! • No time or bandwidth used for cached responses • No application-specific cache bugs code. • Concessions: only supports “safe methods”, caching needs to be tuned.
  • 32. introduction hello http api! hello okhttp! uh oh.. scale! hello http/2! wrapping up
  • 33. http/1.1 • rfc2616 - June 1999 • text-based framing • defined semantics of the web http://www.w3.org/Protocols/rfc2616/rfc2616.html
  • 34. FYI: RFC 2616 is dead! • RFC 7230-5 replaces RFC 2616. • Checkout details on www.mnot.net/blog
  • 35. spdy/3.1 http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1 • google - Sep 2013 • binary framing • retains http/1.1 semantics • concurrent multiplexed streams
  • 36. http/2 https://tools.ietf.org/html/rfc7540 • rfc7540 - May 2015 • binary framing • retains http/1.1 semantics • concurrent multiplexed streams
  • 39. Looking at the whole message Request: request line, headers, and body Response: status line, headers, and body
  • 40. http/1.1 round-trip GZIPPED DATA Content-Length: 318 Cache-Control: private, max-age=60, s- maxage=0 Vary: SecurityToken Date: Sun, 02 Feb 2014 20:30:38 GMT Content-Type: application/json Content-Encoding: gzip Host: apihost SecurityToken: b08c85073c1a2d02 Accept: application/json Accept-encoding: gzip, deflate GET /things HTTP/1.1 HTTP/1.1 200 OK • http/1.1 sends requests and responses one at a time over a network connection
  • 41. http/2 round-trip GZIPPED DATA :status: 200 content-length: 318 cache-control: private, max-age=60, s- maxage=0 vary: SecurityToken date: Sun, 02 Feb 2014 20:30:38 GMT content-type: application/json :method: GET :authority: apihost :path: /things securitytoken: b08c85073c1a2d02 accept: application/json accept-encoding: gzip, deflate HEADERS Stream: 3 Flags: END_HEADERS, END_STREAM HEADERS Stream: 3 Flags: END_HEADERS DATA Stream: 3 Flags: END_STREAM • http/2 breaks up messages into stream-scoped frames
  • 42. Interleaving HEADERS Stream: 5 Flags: END_HEADERS, END_STREAM HEADERS Stream: 3 Flags: END_HEADERS DATA Stream: 5 Flags: DATA Stream: 5 Flags: END_STREAM HEADERS Stream: 3 Flags: END_HEADERS, END_STREAM HEADERS Stream: 5 Flags: END_HEADERS DATA Stream: 3 Flags: END_STREAM • http/2 multiplexes a network connection by interleaving request/response frames
  • 43. Canceling a Stream HEADERS Stream: 5 Flags: END_HEADERS, END_STREAM HEADERS Stream: 3 Flags: END_HEADERS DATA Stream: 5 Flags: HEADERS Stream: 3 Flags: END_HEADERS, END_STREAM HEADERS Stream: 5 Flags: END_HEADERS DATA Stream: 3 Flags: END_STREAM RST_STREAM Stream: 5 ErrorCode: CANCEL • interrupts a response without affecting the connection
  • 44. control frames HEADERS Stream: 5 HEADERS Stream: 3 DATA Stream: 5 DATA Stream: 3 HEADERS Stream: 3 HEADERS Stream: 5 SETTINGS Stream: 0 SETTINGS Stream: 0 DATA Stream: 5 • connection-scoped frames allow runtime updates, like flow-control
  • 47. http/1.1 headers GZIPPED DATA Content-Length: 318 Cache-Control: private, max-age=60, s- maxage=0 Vary: SecurityToken Date: Sun, 02 Feb 2014 20:30:38 GMT Content-Type: application/json Content-Encoding: gzip Host: apihost SecurityToken: b08c85073c1a2d02 Accept: application/json Accept-encoding: gzip, deflate GET /things HTTP/1.1 HTTP/1.1 200 OK 168! 195! 318 • You can gzip data, but not headers!
  • 48. header compression GZIPPED DATA :status: 200 content-length: 318 cache-control: private, max-age=60, s-maxage=0 vary: SecurityToken date: Sun, 02 Feb 2014 20:30:38 GMT content-type: application/json content-encoding: gzip :method: GET :authority: apihost :path: /things securitytoken: b08c85073c1a2d02 accept: application/json accept-encoding: gzip, deflate HEADERS Stream: 3 Flags: END_HEADERS, END_STREAM HEADERS Stream: 3 Flags: END_HEADERS DATA Stream: 3 Flags: END_STREAM 8 bytes 52 bytes compressed 8 bytes 85 bytes compressed • 161 byte overhead instead of 363 8 bytes
  • 49. indexed headers! GZIPPED DATA :status: 200 content-length: 318 cache-control: private, max-age=60, s-maxage=0 vary: SecurityToken date: Sun, 02 Feb 2014 20:30:39 GMT content-type: application/json content-encoding: gzip :method: GET :authority: apihost :path: /things securitytoken: b08c85073c1a2d02 accept: application/json accept-encoding: gzip, deflate HEADERS Stream: 3 Flags: END_HEADERS, END_STREAM HEADERS Stream: 3 Flags: END_HEADERS DATA Stream: 3 Flags: END_STREAM 8 bytes 28 bytes compressed 8 bytes 30 bytes compressed • 82 byte overhead instead of 363 8 bytes
  • 50. hpack http://tools.ietf.org/html/rfc7541 • rfc7540 - May 2015 • static and dynamic table • huffman encoding
  • 52. push promise :method: GET :path: /things ... HEADERS Stream: 3 HEADERS Stream: 3 DATA Stream: 4 :method: GET :path: /users/0 ... PUSH_PROMISE Stream: 3 Promised-Stream: 4 HEADERS Stream: 4 push response goes into cache DATA Stream: 3 Server guesses a future request or indicates a cache invalidation
  • 53. okhttp + http/2 • OkHttp 2.3+ supports http/2 on TLS+ALPN connections. • Works out of the box on Android • Java needs hacks until JEP 244 For now, add jetty’s ALPN to your bootclasspath. * Verify version matches your JRE * $ java -Xbootclasspath/p:/path/to/alpn-boot-8.1.4.v20150727.jar
  • 54. We won! • 1 socket for 100+ concurrent streams. • Advanced features like flow control, cancellation and cache push. • Dramatically less header overhead.
  • 55. okhttp tools • There are tools that leverage OkHttp natively… • including its http/2 features.
  • 56. MockWebServer SSLSocketFactory factory = SslContextBuilder.localhost().getSocketFactory(); OkHttpClient client = new OkHttpClient() .setSslSocketFactory(factory); @Rule public final MockWebServer server = new MockWebServer() .setSslSocketFactory(factory); @Test public void evenWithHttp2SlowResponsesKill() throws Exception { server.enqueue(new MockResponse().setBody(lotsOfThings) .throttleBody(1024, 1, SECONDS)); // slow connection 1KiB/second request = new Request.Builder() .url(server.getUrl(”/”) + ”things”) —snip— • MockWebServer uses http/2 by default when using TLS
  • 57. Retrofit 2 @Headers("Accept-Encoding: gzip, deflate”) interface ThingService { @GET("things") Single<List<Things> list(); // RxJava support! } retrofit = new Retrofit.Builder() .client(client) .baseUrl(“https://apihost/“) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build(); thingsService = retrofit.create(ThingService.class); subscription = thingsService.iist().subscribe(System.out::println) • Retrofit 2 extends OkHttp with api model binding
  • 58. okcurl $ java -Xbootclasspath/p:alpn-boot.jar -jar okcurl.jar https://twitter.com -X HEAD --frames >> CONNECTION 505249202a20485454502f322e300d0a0d0a534d0d0a0d0a << 0x00000000 6 SETTINGS >> 0x00000000 6 SETTINGS >> 0x00000000 4 WINDOW_UPDATE >> 0x00000000 0 SETTINGS ACK >> 0x00000003 60 HEADERS END_STREAM|END_HEADERS << 0x00000000 0 SETTINGS ACK << 0x00000003 2097 HEADERS END_STREAM|END_HEADERS >> 0x00000000 8 GOAWAY
  • 59. introduction hello http api! hello okhttp! uh oh.. scale! hello http/2! wrapping up
  • 60. Engage! • Consider http/2 or at least spdy! • Check-out okhttp and friends • Test http/2 load balancers like google cloud https://github.com/square/okhttp/tree/master/mockwebserver http://square.github.io/retrofit/ https://cloud.google.com/compute/docs/load-balancing/http/