SlideShare une entreprise Scribd logo
1  sur  61
Télécharger pour lire hors ligne
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

Contenu connexe

Tendances

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
 

Tendances (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?
 

En vedette

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
 

En vedette (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
 

Similaire à 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
 

Similaire à 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
 

Dernier

Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 

Dernier (20)

Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 

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/