100
Everything You Wanted to Know About Writing Async, Concurrent HTTP Apps in Java

Everything you wanted to know about writing async, concurrent http apps in java

Embed Size (px)

Citation preview

Page 1: Everything you wanted to know about writing async, concurrent http apps in java

Everything You Wanted to

Know

About Writing Async,

Concurrent HTTP Apps in Java

Page 2: Everything you wanted to know about writing async, concurrent http apps in java

Agenda

• Mostly this:

Page 3: Everything you wanted to know about writing async, concurrent http apps in java

Agenda

• And this:

Page 4: Everything you wanted to know about writing async, concurrent http apps in java

Agenda

• And this:

Page 5: Everything you wanted to know about writing async, concurrent http apps in java

About your speaker

linkd.in/jbaruch

stackoverflow.com/users/402053/jbaruch

Page 6: Everything you wanted to know about writing async, concurrent http apps in java

What Frog?

Page 7: Everything you wanted to know about writing async, concurrent http apps in java

What Frog?

Page 8: Everything you wanted to know about writing async, concurrent http apps in java

What Frog?

Page 9: Everything you wanted to know about writing async, concurrent http apps in java

What Frog?

Page 10: Everything you wanted to know about writing async, concurrent http apps in java
Page 11: Everything you wanted to know about writing async, concurrent http apps in java
Page 12: Everything you wanted to know about writing async, concurrent http apps in java

Requirements

– parallel file Downloads

– Parallel file parts

– interrupt/pause/resume

– Progress events

– Checksums caching

Page 13: Everything you wanted to know about writing async, concurrent http apps in java

First Association for “concurrent

downloader”

Page 14: Everything you wanted to know about writing async, concurrent http apps in java
Page 15: Everything you wanted to know about writing async, concurrent http apps in java

Lucky day: Download manager

written in java!

Page 16: Everything you wanted to know about writing async, concurrent http apps in java
Page 17: Everything you wanted to know about writing async, concurrent http apps in java

Let’s look if we can use it!

1. No traceable license2. No website or docs3. No traceable sources4. It’s an app, not a lib

Page 18: Everything you wanted to know about writing async, concurrent http apps in java
Page 19: Everything you wanted to know about writing async, concurrent http apps in java
Page 20: Everything you wanted to know about writing async, concurrent http apps in java

Java.net.urlconnection

1. Memory wasteful (buffering)

2. Minimal API

3. Blocking streams

Page 21: Everything you wanted to know about writing async, concurrent http apps in java
Page 22: Everything you wanted to know about writing async, concurrent http apps in java

What we’re looking for

1. Async/non-blocking

2. Event callbacks

Page 23: Everything you wanted to know about writing async, concurrent http apps in java

What is IT going to take

1. Reactor

2. nio

Page 24: Everything you wanted to know about writing async, concurrent http apps in java

Welcome to the reactor

Page 25: Everything you wanted to know about writing async, concurrent http apps in java

– pattern for lightweight concurrency

– Event driven

– Threads reuse

– Uses non-blocking Io

Page 26: Everything you wanted to know about writing async, concurrent http apps in java

Original pattern

http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf

Page 27: Everything you wanted to know about writing async, concurrent http apps in java

Guess the author by the

diagram

http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf

Page 28: Everything you wanted to know about writing async, concurrent http apps in java

In Java, Reactor means NIO

Page 29: Everything you wanted to know about writing async, concurrent http apps in java

Selector as a multiplexer

Page 30: Everything you wanted to know about writing async, concurrent http apps in java

Java version - Registering

SocketChannel channel= SocketChannel.open();

socketChannel.connect(new

InetSocketAddress("http://remote.com", 80));

...

Selector selector = Selector.open();

channel.configureBlocking(false);

SelectionKey k = channel.register(selector,

SelectionKey.OP_READ);

k.attach(handler);

Page 31: Everything you wanted to know about writing async, concurrent http apps in java

Java version - Dispatcher

while (!Thread.interrupted()) {

selector.select();

Set selected = selector.selectedKeys();

Iterator it = selected.iterator();

while (it.hasNext())

SelectionKey k = (SelectionKey)(it.next();

((Runnable)(k.attachment())).run();

selected.clear();

}

Page 32: Everything you wanted to know about writing async, concurrent http apps in java

Handling reactor events is complex

– Need to maintain state

– Buffering – assembling chunks

– Coordinating async events

Page 33: Everything you wanted to know about writing async, concurrent http apps in java
Page 34: Everything you wanted to know about writing async, concurrent http apps in java

Nio libraries

– Most of them are servers–Netty, grizzly, etc.

– Apache Mina– Apache HTTP components asyncclient– Ning http client

Page 35: Everything you wanted to know about writing async, concurrent http apps in java

– Client and server nio library

– Evolved from netty

– Latest release October 2012

Page 36: Everything you wanted to know about writing async, concurrent http apps in java
Page 37: Everything you wanted to know about writing async, concurrent http apps in java

Nio libraries

– Most of them are servers–Netty, grizzly, etc

– Apache Mina– Apache HTTP components asyncclient– Ning http client

Page 38: Everything you wanted to know about writing async, concurrent http apps in java
Page 39: Everything you wanted to know about writing async, concurrent http apps in java

Ning’s async http client

Page 40: Everything you wanted to know about writing async, concurrent http apps in java
Page 41: Everything you wanted to know about writing async, concurrent http apps in java
Page 42: Everything you wanted to know about writing async, concurrent http apps in java

Here it is!

Page 43: Everything you wanted to know about writing async, concurrent http apps in java

try (AsyncHttpClient asyncHttpClient = new AsyncHttpClient()) {

ListenableFuture<Response> future = asyncHttpClient.prepareGet(

"http://oss.jfrog.org/api/system/ping").execute(

new AsyncCompletionHandler<Response>() {

@Override

public Response onCompleted(Response response) {

System.out.println(response.getResponseBody());

return response;

}

@Override

public void onThrowable(Throwable t) {

t.printStackTrace();

}

});

Response response = future.get();

}

Page 44: Everything you wanted to know about writing async, concurrent http apps in java
Page 45: Everything you wanted to know about writing async, concurrent http apps in java

HAC Concepts

– Request producer

– Response consumer

Page 46: Everything you wanted to know about writing async, concurrent http apps in java

try(CloseableHttpAsyncClientasyncHttpClient=HttpAsyncClients.createDefault()){asyncHttpClient.start();Future<HttpResponse>future=asyncHttpClient.execute(HttpAsyncMethods.createGet("http://oss.jfrog.org/api/system/ping"),newAsyncByteConsumer<HttpResponse>(){@OverrideprotectedvoidonResponseReceived(finalHttpResponseresponse){System.out.println(response.getStatusLine().getReasonPhrase());}@OverrideprotectedvoidonByteReceived(finalCharBufferbuf,finalIOControlioctrl){}@OverrideprotectedvoidreleaseResources(){}@OverrideprotectedHttpResponsebuildResult(finalHttpContextcontext){return(HttpResponse)context.getAttribute("http.response");}},null);HttpResponseresponse=future.get();}

Page 47: Everything you wanted to know about writing async, concurrent http apps in java
Page 48: Everything you wanted to know about writing async, concurrent http apps in java

Choosing between ning and http

asyncclient

Page 49: Everything you wanted to know about writing async, concurrent http apps in java

"All problems in computer science can

be solved by another level of

indirection"David

Wheeler

Page 50: Everything you wanted to know about writing async, concurrent http apps in java

public interface HttpProviderDownloadHandler {

void onResponseReceived(int statusCode, Map<String, List<String>> headers);

boolean onBytesReceived(ByteBuffer buf);

void onFailed(Throwable error);

void onCanceled();

void onCompleted();}

Page 51: Everything you wanted to know about writing async, concurrent http apps in java

Head to head

Feature/Library Ning client Http Async Client

Maturity Good Very new (early 2014)

Download cancelation Easy With bugs

Progress hooks Events not granular enough

Just use onByteReceived()

Documentation A bit sparse Minimal

Server-side counterpart None, client only org.apache.httpcomponentshttpcore-nio

Page 52: Everything you wanted to know about writing async, concurrent http apps in java

Performance?

0

100

200

300

400

500

600

700

800

900

Small file Medium file Large file

Ning

AHAC

http://blogs.atlassian.com/2013/07/http-client-performance-io/

Page 53: Everything you wanted to know about writing async, concurrent http apps in java

Rfc2616: a universe of its own

Page 54: Everything you wanted to know about writing async, concurrent http apps in java
Page 55: Everything you wanted to know about writing async, concurrent http apps in java

Confused?

Page 56: Everything you wanted to know about writing async, concurrent http apps in java

Just read some stackoverflow

(and improve your rep as you go)

Page 57: Everything you wanted to know about writing async, concurrent http apps in java

And that one for discovering that range header is lost on redirect

Page 58: Everything you wanted to know about writing async, concurrent http apps in java

Question!

What should be

content-length

when using

compression?

Page 59: Everything you wanted to know about writing async, concurrent http apps in java
Page 60: Everything you wanted to know about writing async, concurrent http apps in java
Page 61: Everything you wanted to know about writing async, concurrent http apps in java

https://github.com/http2/http2-spec/issues/46

Page 62: Everything you wanted to know about writing async, concurrent http apps in java

Question!

Why when redirected to CDN all the chunks start from zero?

Page 63: Everything you wanted to know about writing async, concurrent http apps in java

HttpAsyncClientBuilder builder = HttpAsyncClients.custom();// add redirect strategy that copies "range" headers, if existbuilder.setRedirectStrategy(new DefaultRedirectStrategy() {

@Overridepublic HttpUriRequest getRedirect(HttpRequest request, HttpResponse response,

HttpContext context)HttpUriRequest redirectRequest = super.getRedirect(request, response, context);// copy "Range" headers, if existHeader[] rangeHeaders = request.getHeaders(HttpHeaders.RANGE);if (rangeHeaders != null) {

for (Header header : rangeHeaders) {redirectRequest.addHeader(header);

}}return redirectRequest;

}});

Page 64: Everything you wanted to know about writing async, concurrent http apps in java

Question!

How many simultaneous

connections should I open?

Page 65: Everything you wanted to know about writing async, concurrent http apps in java
Page 66: Everything you wanted to know about writing async, concurrent http apps in java
Page 67: Everything you wanted to know about writing async, concurrent http apps in java
Page 68: Everything you wanted to know about writing async, concurrent http apps in java
Page 69: Everything you wanted to know about writing async, concurrent http apps in java

Question!

What’s wrong

with the

following

code?

Page 70: Everything you wanted to know about writing async, concurrent http apps in java

public static String encodeUrl(String urlStr) {URLEncoder.encode(urlStr, "UTF-8");...

}

Page 71: Everything you wanted to know about writing async, concurrent http apps in java

Decoded URLs cannot be

re-encoded to the same form

http://example.com/?query=a&b==c

Cannot be decoded back after it was encoded:

http://example.com/?query=a%26b==c

Page 72: Everything you wanted to know about writing async, concurrent http apps in java

Don’t use java.net.URLEncoder

“Utility class for HTML form encoding. This class contains static methods for converting a String to the application/x-www-form-urlencoded MIME format.

For more information about HTML form encoding, consult the HTML specification.”

Page 73: Everything you wanted to know about writing async, concurrent http apps in java

AHC Alternatives

Page 74: Everything you wanted to know about writing async, concurrent http apps in java
Page 75: Everything you wanted to know about writing async, concurrent http apps in java

Question!

How do I

close a

socket

correctly?

Page 76: Everything you wanted to know about writing async, concurrent http apps in java

How hard can it be to close a

socket?

Page 77: Everything you wanted to know about writing async, concurrent http apps in java

The art of socket closing

http://www.safaribooksonline.com/library/view/http-the-definitive/1565925092/ch04s07.html

Page 78: Everything you wanted to know about writing async, concurrent http apps in java

Half-closed: no new customers

Page 79: Everything you wanted to know about writing async, concurrent http apps in java

Never block in socket close()

• The other side expects you

to clean up nicely

• It will give up on time out

• You will wait (forever)

Page 80: Everything you wanted to know about writing async, concurrent http apps in java
Page 81: Everything you wanted to know about writing async, concurrent http apps in java

Remember?

Page 82: Everything you wanted to know about writing async, concurrent http apps in java

Question!

How can I write

file parts

concurrently?

Page 83: Everything you wanted to know about writing async, concurrent http apps in java

– Write to separate files, combine on finish

– Write to same file, seeking to the right position

Page 84: Everything you wanted to know about writing async, concurrent http apps in java
Page 85: Everything you wanted to know about writing async, concurrent http apps in java
Page 86: Everything you wanted to know about writing async, concurrent http apps in java

USE FileChannel

• Implements SeekableByteChannel

java.nio.channels.FileChannel#write(java.nio.ByteBuffer src, long position)

Page 87: Everything you wanted to know about writing async, concurrent http apps in java

download progress tracking

• PersistentFileProgressInfo– Save the total size, sha1, number of parts

– State of each part (offset, size, completed...)

FileProgressInfo FilePartProgressInfo*

Page 88: Everything you wanted to know about writing async, concurrent http apps in java

File Locking

Page 89: Everything you wanted to know about writing async, concurrent http apps in java

File locking Levels

– VM level

– OS level

Page 90: Everything you wanted to know about writing async, concurrent http apps in java

OS level File locking

• Multiple downloader instances writing to

the same file

• Needed for writing:

– Partial download file

– Persistent download progress

Page 91: Everything you wanted to know about writing async, concurrent http apps in java

FileLock lock = fileChannel.tryLock();//Non-shared: (0L, Long.MAX_VALUE, false)

if (lock == null) {throw new OverlappingFileLockException();

}return lock;

}

OS Level File Locking -

Exclusive

Page 92: Everything you wanted to know about writing async, concurrent http apps in java

private FileLock lock(FileChannel fileChannel) throws IOException {FileLock lock = fileChannel.tryLock(Long.MAX_VALUE - 1, 1, false);if (lock == null) {

throw new OverlappingFileLockException();}return lock;

}

OS Level File Locking –

Advisory exclusive

WTF?!

Page 93: Everything you wanted to know about writing async, concurrent http apps in java

VM Level File Locking

Page 94: Everything you wanted to know about writing async, concurrent http apps in java

VM Level File Locking– Prevent same VM threads writing to the file when we

started closing it– Closing sequence:

– Release file locks– Close channels– Rename a file to it's final name (remove .part)– Erase progress info

Page 95: Everything you wanted to know about writing async, concurrent http apps in java

VM Level File LockingReentrantReadWriteLock.ReadLock writeToFileLock = rwl.readLock();ReentrantReadWriteLock.WriteLock closeFileLock = rwl.writeLock();

public void close() throws IOException {this.closeFileLock.lock();

}

public int write(int partIndex, ByteBuffer buf) {if (!this.writeToFileLock.tryLock()) {

throw new IllegalStateException("File is being closed");}...

}

Page 96: Everything you wanted to know about writing async, concurrent http apps in java

What’s next?

Page 97: Everything you wanted to know about writing async, concurrent http apps in java

http/2– Mostly standardizing Google's spdy– Header compression– multiplexing– Prioritization– Server push– On the way clear some stuff– E.g. compressed content length

Page 98: Everything you wanted to know about writing async, concurrent http apps in java

Ease the load

Page 100: Everything you wanted to know about writing async, concurrent http apps in java

No, Thank you!