everything you wanted to know about writing async, high-concurrency http apps in java, but were...

101
НЕ ВСЁ, НО МНОГОЕ О ТОМ, ЧТО ВЫ ХОТЕЛИ ЗНАТЬ О ТОМ, КАК НАПИСАТЬ АСИНХРОННЫЕ МНОГОПОТОЧНЫЕ HTTP ПРИЛОЖЕНИЯ, НО БОЯЛИСЬ СПРОСИТЬ.

Upload: javadayua

Post on 06-Jan-2017

272 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

НЕ ВСЁ,  НО МНОГОЕ О ТОМ, ЧТО ВЫ ХОТЕЛИ

ЗНАТЬ О ТОМ, КАК НАПИСАТЬ

АСИНХРОННЫЕ МНОГОПОТОЧНЫЕ HTTP

ПРИЛОЖЕНИЯ, НО БОЯЛИСЬ СПРОСИТЬ.

Page 2: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Краткое содержание• В основном такое:

Page 3: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Краткое содержание• И такое:

Page 4: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Краткое содержание• И такое:

Page 5: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Бáрух это я[email protected]/jbaruch

linkd.in/jbaruch

stackoverflow.com/users/402053/jbaruch

Page 6: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

А КОМУ БИНАРНИКИ?

Page 7: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

ПАРАЛЛЕЛЬНЫЕ ЗАГРУЗКИ

ПОЧЕМУ ВЫ ИХ НЕ УМЕЕТЕ?!

Page 8: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Требования– Параллельные загрузки файлов– Параллельная загрузка файла– Прерывания и паузы– Мониторинг процесса– Кэширование по контрольной

сумме

Page 9: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Игра в ассоциации: «Менеджер Загрузок»

Page 10: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky
Page 11: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

О, нашли, написан на Java!

Page 12: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

НЕЛЬЗЯ ПРОСТО ТАК ВЗЯТЬ

И ВЗЯТЬ JDM

Page 13: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Ну, берем, не?!1.Ни следа лицензии2.Ни сайта, ни доков3.Ни следа исходников4.Да и вообще, это

приложение, а не библиотека

Page 14: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

ХОЧЕШЬ ХОРОШИЙ МЕНЕДЖЕР ЗАГРУЗОК?

ПИШИ ЕГО САМ!

Page 15: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

ДА ЛАНА, ВЗЯЛ URLCONNECTION

И ПОШЛА, ПОШЛА, ПОШЛА!

Page 16: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Java.net.urlconnection1. Все проходит через память2. нет нормального API3. блокирует потоки

Page 17: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Не блокируй!

Page 18: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Что мы ищем:1. Асинхронный/не блокирующий2. С коллбэками на эвенты

Page 19: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Что для этого понадобится:1. реактор2. nio

Page 20: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Добро пожаловать в Реактор

Page 21: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

– Паттерн для легковесной многопоточности

– Событийный– повторное использование потоков– Не блокирующий IO

Page 22: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Вот как-то так:

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

Page 23: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Угадайте, кто рисовал

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

Page 24: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

В Джаве говорим «реактор»,

подразумеваем NIO.

Page 25: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Селектор проводит селекцию

Page 26: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Код! На Java! Регистрация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 27: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Код! На Java! Распределение

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 28: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Обработка событий в реакторе – сложная штука

– Надо помнить состояние– Буфферизация – надо собирать

куски файлов– надо координировать события

Page 29: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

ЭТО НИО – ТЕЛОХРАНИТЕЛЬ БУДДЫ

ОН СИЛЁН

Page 30: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Библиотеки Nio– В основном серверные

– Netty, grizzly, etc.– Apache Mina– Apache HTTP components

asyncclient – Ning http client

Page 31: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Библиотеки Nio– В основном серверные

– Netty, grizzly, etc.– Apache Mina– Apache HTTP components

asyncclient – Ning http client

Page 32: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

– Серверная и клиентская nio библиотека

– Отпочковалась от netty– Последний релиз: октябрь 2012

Page 33: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky
Page 34: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Библиотеки Nio– В основном серверные

– Netty, grizzly, etc– Apache Mina– Apache HTTP components

asyncclient – Ning http client

Page 35: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky
Page 36: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Ning’s Async HTTP Client

Page 37: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky
Page 38: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky
Page 39: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

А вот она!

Page 40: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

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 41: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky
Page 42: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Концепции HAC– Request producer– Response consumer

Page 43: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky
Page 44: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

ОПАЧКИ…

ОНИ ЖЕ ОДИНАКОВЫЕ!

Page 45: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Это мы, выбираем между ning и http asyncclient

Page 46: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

«Каждая компьютерная проблема решается еще одним уровнем абстракции»

Дэвид Уиллер

Page 47: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

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 48: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Фича/Библиотека

Ning client Http Async Client

Матёрость Хорошая Совсем зеленый (начало 2014)

Отмена закачек Легко Не без баговМониторинг прогресса

Не достаточно мелкие события

Да вот же: onByteReceived()

Документация Оставляет желать лучшего

Скорее нет, чем есть

Серверная составляющая

Нет, только клиент

org.apache.httpcomponentshttpcore-nio

Но всё таки надо выбирать

Page 49: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Как с перфромансом?

Small file Medium file Large file0

100

200

300

400

500

600

700

800

900

NingAHAC

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

Page 50: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Rfc2616: Целая вселенная

Page 51: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky
Page 52: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Совсем запутались?

Page 53: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Вперед, на StackOverflow.Заодно и репутацию прокачаете.

Page 54: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

А эту, когда понял, что

range header теряется при

редиректе

ИЗ ОКОПОВ HTTP

Page 55: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

У меня вопрос!Каким должен быть content-length если используется сжатие?

Page 56: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky
Page 57: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky
Page 58: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

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

Page 59: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

У меня вопрос!

Почему при редиректе на CDN файл начинает качаться с нуля?

Page 60: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

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 61: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

У меня вопрос!Сколько одновременных закачек можно ставить?

Page 62: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

HTTP 1.1 ТАКОЙ:

МОЖНО, ПОЖАЛУЙСТА, НЕ БОЛЬШЕ 2 ПОДКЛЮЧЕНИЙ?

Page 63: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

БРАУЗЕРЫ ТАКИЕ:

Page 64: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky
Page 65: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

URL ENCODING?

Page 66: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

У меня вопрос!Что не так с этим кодом?

Page 67: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

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

Page 68: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Закодированное URLEncoder-ом не раскодируешь обратно…

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

Нельзя раскодировать обратно после того, как закодируешь:

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

Page 69: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Не пользуйтесь 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 70: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

У AHC есть способы лучшеorg.apache.http.client.utils.URIBuilder

org.apache.http.client.utils.URLEncodedUtils

Page 71: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky
Page 72: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

У меня вопрос!Как правильно закрывать сокет?

Page 73: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Да ладно, чего там сложного?

Page 74: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Трактат о закрывании сокета

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

Page 75: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Полузакрыто: «магазин закрывается, проходите к

кассам»

Page 76: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Не блокируйте в close()!• Сервер ожидает, что вы

закроете как надо• В какой-то момент ему

надоест• А вы так и будете ждать

Page 77: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Я ВСЕГДА ЗАКРЫВАЮПОДКЛЮЧЕНИЯ

И КОГДА Я ЭТО ДЕЛАЮ,Я ПОЛЬЗУЮСЬ

TRY-WITH-RESOURCES

Page 78: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Вот, и Чак одобряэ.

Page 79: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

У меня вопрос!Как писать куски файлов параллельно?

Page 80: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

– Писать в разные файлы, собирать в один в конце

– Писать в тот-же файл, начиная с правильного места

Page 81: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

НУ ТАК ЕСТЬ ЖЕ ДЛЯ ТАКОГО

JAVA.IO.RANDOMACCESSFILE?!

Page 82: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky
Page 83: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Пользуемся FileChannel• Реализует SeekableByteChannel

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

Page 84: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Отслеживаем прогресс

• PersistentFileProgressInfo– Сохраняем размер, чексамы, количество частей– Состояние каждой части(отступ, размер,

состояние...)

FileProgressInfo FilePartProgressInfo*

Page 85: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Локинг файлов

Page 86: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Уровни локинга– Уровень JVM– Уровень операционной системы

Page 87: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Уровень ОС– Защита от дурака: Несколько

приложений скачивают тот же файл в то же место

– Надо лочить:– Частично закаченный файл– Сохраненный на диск прогресс

Page 88: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Легко, нам нужен shared lock!

• Один пишет, остальные смотрят читают

Page 89: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

java.io.IOException "The process cannot access the file because another process has locked a portion of

the file"

Page 90: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Windowz…

Page 91: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

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;}

На каждую хитрую Винду свой StackOverflow с винтом

Щито?!

Page 92: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Локинг на уровне VMДА ЗАЧЕМ ЛОКИ-

ТО?

ПИШЕМ ЖЕ В РАЗНЫЕ ЧАСТИ

ФАЙЛА!

Page 93: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Локинг на уровне VM– Закрывать файл должен только один поток– Процесс закрытия:

– Снять локи ОС– Закрыть channels– Переименовать файл в конечный вид

(убрать .part)– Стереть файл прогресса

Page 94: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Локинг на уровне VMReentrantReadWriteLock.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 95: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Будущее…

Page 96: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Будущее уже (почти) здесь!

Page 97: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

http/2– В основном стандартизирует spdy от Google– Компрессия хидеров – мультиплексирование– приоритизация– Сервер пуш– Ну и прояснить всякие моменты

– Например длинна сжатого контента

Page 98: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

Мультиплексинг, фреймы и сервер-пуш

Page 99: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky

У меня вопрос!Сколько одновременных закачек можно ставить в HTTP/2?

Page 101: Everything you wanted to know about writing async, high-concurrency HTTP apps in Java, but were afraid to ask by Baruch Sadogursky