Книжная полка Сохранить
Размер шрифта:
А
А
А
|  Шрифт:
Arial
Times
|  Интервал:
Стандартный
Средний
Большой
|  Цвет сайта:
Ц
Ц
Ц
Ц
Ц

Реактивное программирование с применением RxJava

Покупка
Артикул: 698120.02.99
Доступ онлайн
849 ₽
В корзину
В наши дни, когда программы асинхронны, а быстрая реакция - важнейшее свойство, реактивное программирование поможет писать более надежный, лучше масштабируемый и быстрее работающий код. Благодаря этой книге программист на Java узнает о реактивном подходе к задачам и научится создавать программы, вобравшие в себя лучшие черты этой новой и весьма перспективной парадигмы. Данная книга содержит глубокое и подробное изложение концепций и принципов использования реактивного программирования вообще и Rxjava в частности. Книга может использоваться как для последовательного изучения предмета, так и в качестве справочника по библиотеке.
Нуркевич, Т. Реактивное программирование с применением Rxjava / Томаш Нуркевич, Бен Кристенсен ; пер. с англ. А.А. Слинкина. - Москва : ДМК Пресс, 2017. - 358 с. - ISBN 978-5-97060-496-0. - Текст : электронный. - URL: https://znanium.com/catalog/product/1027762 (дата обращения: 19.04.2024). – Режим доступа: по подписке.
Фрагмент текстового слоя документа размещен для индексирующих роботов. Для полноценной работы с документом, пожалуйста, перейдите в ридер.
Томаш Нуркевич, Бен Кристенсен

Реактивное 
программирование 
с применением  
RxJava

Beijing • Cambridge • Farnham • Köln • Sebastopol • Tokyo

Reactive  
Programming 
with RxJava

Creating Asynchronous,  
Event-Based Applications

Tomasz Nurkiewicz and Ben Christensen

Москва, 2017

Реактивное 
программирование 
с применением RxJava

Разработка асинхронных  
событийно-ориентированных приложений

Томаш Нуркевич, Бен Кристенсен

УДК  004.738.5:004.438 RxJava
ББК   32.973.2

М15

М15   Томаш Нуркевич, Бен Кристенсен

Реактивное программирование с применением RxJava / пер. с англ. Слинкин А. А. – М.: ДМК Пресс, 2017. – 358 с.: ил.

ISBN 978-5-97060-496-0

В наши дни, когда программы асинхронны, а быстрая реакция – важ
нейшее свойство, реактивное программирование поможет писать более 
надежный, лучше масштабируемый и быстрее работающий код. Благодаря 
этой книге программист на Java узнает о реактивном подходе к задачам и 
научится создавать программы, вобравшие в себя лучшие черты этой новой 
и весьма перспективной парадигмы. Данная книга содержит глубокое и 
подробное изложение концепций и принципов использования реактивного 
программирования вообще и RxJava в частности.

Книга может использоваться как для последовательного изучения пред
мета, так и в качестве справочника по библиотеке.

                                                                  УДК   004.738.5:004.438 RxJava
                                                                  ББК   32.973.2

Authorized Russian translation of the English edition of Reactive Programming with RxJava, 

ISBN 9781491931653. © 2017 Ben Christensen and Tomasz Nurkiewicz. This translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls all rights to publish 
and sell the same.

Все права защищены. Любая часть этой книги не может быть воспроизведена 

в какой бы то ни было форме и какими бы то ни было средствами без письменного 
разрешения владельцев авторских прав.

Материал, изложенный в данной книге, многократно проверен. Но, поскольку 

вероятность технических ошибок все равно существует, издательство не может гарантировать абсолютную точность и правильность приводимых сведений. В связи 
с этим издательство не несет ответственности за возможные ошибки, связанные с 
использованием книги.

ISBN 978-1-49193-165-3 (англ.)                  © Ben Christensen and Tomasz Nurkiewicz, 2017.
ISBN 978-5-97060-496-0 (рус.)                    © Перевод на русский язык, оформление,

               издание, ДМК Пресс, 2017

Посвящается Паулине Сьцежка, самому честному и прямому человеку 

из всех моих знакомых.

За доверие и помощь, отнюдь не ограничивающуюся написанием книги.

За мою жизнь, которую она изменила в куда большей степени, 

чем может себе представить.

– Томаш Нуркевич

Оглавление

Предисловие..................................................................11

Вступление....................................................................14
Для кого написана эта книга ................................................................. 14
Несколько слов от Бена Кристенсена .................................................... 14
Несколько слов от Томаша Нуркевича ................................................... 16
О содержании книги ............................................................................. 16
Ресурсы в Сети ..................................................................................... 17
Графические выделения ....................................................................... 17
Как с нами связаться ............................................................................ 18
Благодарности ..................................................................................... 18
От Бена ........................................................................................................ 18
От Томаша .................................................................................................... 19

Глава.1..Реактивное.программирование..
с.применением.RxJava.....................................................20
Реактивное программирование и RxJava .............................................. 20
Когда возникает нужда в реактивном программировании ..................... 22
Как работает RxJava .............................................................................. 23
Проталкивание и вытягивание ...................................................................... 23
Синхронный и асинхронный режим .............................................................. 25
Конкурентность и параллелизм .................................................................... 28
Ленивые и энергичные типы ......................................................................... 31
Двойственность ........................................................................................... 33
Одно или несколько? .................................................................................... 34
Учет особенностей оборудования: блокирующий и неблокирующий  
ввод-вывод ........................................................................................... 39
Абстракция реактивности ..................................................................... 44

Глава.2..Реактивные.расширения.......................................45
Анатомия rx.Observable ......................................................................... 45
Подписка на уведомления от объекта Observable .................................. 48
Получение всех уведомлений с помощью типа Observer<T> ........................ 50
Управление прослушивателями с помощью типов Subscription 
и Subscriber<T> .................................................................................... 50

Оглавление

Создание объектов Observable ............................................................. 52
Подробнее о методе Observable.create() ...................................................... 53
Бесконечные потоки ..................................................................................... 56
Хронометраж: операторы timer() и interval() .................................................. 61
Горячие и холодные объекты Observable ....................................................... 61
Практический пример: от API обратных вызовов к потоку Observable .... 63
Управление подписчиками вручную ............................................................. 68
Класс rx.subjects.Subject ....................................................................... 69
Тип ConnectableObservable ................................................................... 71
Реализация единственной подписки с помощью publish().refCount() ............ 72
Жизненный цикл ConnectableObservable ...................................................... 74
Резюме ................................................................................................. 77

Глава.3..Операторы.и.преобразования................................79
Базовые операторы: отображение и фильтрация .................................. 79
Взаимно однозначные преобразования с помощью map() ........................... 81
Обертывание с помощью flatMap() ............................................................... 85
Откладывание событий с помощью оператора delay() .................................. 90
Порядок событий после flatMap() ................................................................. 91
Сохранение порядка с помощью concatMap() .............................................. 93
Более одного объекта Observable ......................................................... 95
Обращение с несколькими объектами Observable, как с одним,  
с помощью merge() ...................................................................................... 95
Попарная композиция с помощью zip() и zipWith() ........................................ 97
Когда потоки не синхронизированы: combineLatest(), withLatestFrom()  
и amb() ........................................................................................................100
Более сложные операторы: collect(), reduce(), scan(), distinct()  
и groupBy() ......................................................................................... 106
Просмотр последовательности с помощью Scan и Reduce ..........................106
Редукция с помощью изменяемого аккумулятора: collect() ..........................108
Проверка того, что Observable содержит ровно один элемент,  
с помощью single() ......................................................................................109
Устранение дубликатов с помощью distinct() и distinctUntilChanged().... 110
Выборка с помощью операторов skip(), takeWhile() и прочих .......................112
Способы комбинирования потоков: concat(), merge() и switchOnNext() ........114
Расщепление потока по условию с помощью groupBy() ...............................121
Написание пользовательских операторов........................................... 125
Повторное использование операторов с помощью compose().....................125
Реализация более сложных операторов с помощью lift() .............................127
Резюме ............................................................................................... 133

Глава.4..Применение.реактивного.программирования.
в.существующих.приложениях.........................................134
От коллекций к Observable .................................................................. 135
BlockingObservable: выход из реактивного мира ................................. 135

Оглавление

О пользе лени ..................................................................................... 138
Композиция объектов Observable ....................................................... 140
Ленивое разбиение на страницы и конкатенация ........................................141
Императивная конкурентность ........................................................... 142
flatMap() как оператор асинхронного сцепления ................................. 148
Замена обратных вызовов потоками ................................................... 153
Периодический опрос изменений ....................................................... 156
Многопоточность в RxJava .................................................................. 157
Что такое диспетчер? ..................................................................................158
Декларативная подписка с помощью subscribeOn() .....................................167
Конкурентность и поведение subscribeOn() .................................................171
Создание пакета запросов с помощью groupBy() ........................................175
Декларативная конкурентность с помощью observeOn() ..............................177
Другие применения диспетчеров ................................................................180
Резюме ............................................................................................... 181

Глава.5..Реактивность.сверху.донизу................................183
Решение проблемы C10k .................................................................... 183
Традиционные HTTP-серверы на основе потоков ........................................185
Неблокирующий HTTP-сервер на основе Netty и RxNetty .............................187
Сравнение производительности блокирующего и реактивного сервера .....195
Обзор реактивных HTTP-серверов ..............................................................200
Код HTTP-клиента ............................................................................... 201
Доступ к реляционной базе данных ..................................................... 205
NOTIFY и LISTEN на примере PostgreSQL .....................................................207
CompletableFuture и потоки ................................................................. 211
Краткое введение в CompletableFuture ........................................................211
Сравнение типов Observable и Single .................................................. 220
Создание и потребление объектов типа Single ............................................221
Объединение ответов с помощью zip, merge и concat ..................................223
Интероперабельность с Observable и CompletableFuture ..................... 225
Когда использовать тип Single? ...................................................................226
Резюме ............................................................................................... 227

Глава.6..Управление.потоком.и.противодавление................228
Управление потоком ........................................................................... 228
Периодическая выборка и отбрасывание событий ......................................228
Скользящее окно ........................................................................................237
Пропуск устаревших событий с помощью debounce()..................................238
Противодавление ............................................................................... 243
Противодавление в RxJava ..........................................................................244
Встроенное противодавление .....................................................................247
Производители и исключение MissingBackpressureException ......................250
Учет запрошенного объема данных .............................................................253
Резюме ............................................................................................... 259

Оглавление

Глава.7..Тестирование.и.отладка......................................260
Обработка ошибок .............................................................................. 260
А где же мои исключения? ...........................................................................261
Декларативная замена try-catch ..................................................................264
Таймаут в случае отсутствия событий ..........................................................268
Повтор после ошибки ..................................................................................271
Тестирование и отладка ...................................................................... 275
Виртуальное время .....................................................................................275
Диспетчеры и автономное тестирование ....................................................277
Автономное тестирование...........................................................................279
Мониторинг и отладка......................................................................... 287
Обратные вызовы doOn…() .........................................................................287
Измерение и мониторинг ............................................................................289
Резюме ............................................................................................... 292

Глава.8..Практические.примеры.......................................293
Применение RxJava в разработке программ для Android ..................... 293
Предотвращение утечек памяти в компонентах Activity ................................294
Библиотека Retrofit со встроенной поддержкой RxJava ...............................296
Диспетчеры в Android ..................................................................................301
События пользовательского интерфейса как потоки ...................................304
Управление отказами с помощью Hystrix............................................. 307
Hystrix: первые шаги ....................................................................................308
Неблокирующие команды и HystrixObservableCommand ..............................310
Паттерн Переборка и быстрое прекращение ...............................................311
Пакетирование и объединение команд .......................................................313
Мониторинг и инструментальные панели ....................................................318
Опрос баз данных NoSQL .................................................................... 321
Клиенстский API Couchbase ........................................................................322
Клиентский API MongoDB ............................................................................323
Интеграция с Camel ............................................................................ 325
Потребление файлов с помощью Camel ......................................................325
Получение сообщений от Kafka ...................................................................326
Потоки Java 8 и CompletableFuture ...................................................... 326
Полезность параллельных потоков ..............................................................328
Выбор подходящей абстракции конкурентности .........................................330
Когда выбирать Observable? ........................................................................331
Потребление памяти и утечки ............................................................. 332
Операторы, потребляющие неконтролируемый объем памяти ....................332
Резюме ............................................................................................... 337

Глава.9..Направления.будущего.развития..........................338
Реактивные потоки ............................................................................. 338
Типы Observable и Flowable ................................................................. 338
Производительность .......................................................................... 339

Оглавление

Миграция ............................................................................................ 340

Приложение.А..Дополнительные.примеры..
HTTP-серверов..............................................................341
Системный вызов fork() в программе на C .......................................... 341
Один поток – одно подключение ......................................................... 343
Пул потоков для обслуживания подключений ..............................................345

Приложение.B..Решающее.дерево.для.выбора..
операторов.Observable...................................................347

Об.авторах...................................................................352

Об.изображении.на.обложке............................................352

Предметный.указатель...................................................353

Предисловие

28 октября 2005 года Рэй Оззи (Ray Ozzie), только что назначенный главным архитектором Майкрософт, разослал своим сотрудникам получившее скандальную 
известность письмо, озаглавленное «Крах Интернет-служб». В нем он по сути 
дела описывает тот мир, который мы знаем сегодня, – мир, где такие корпорации, 
как Microsoft, Google, Facebook, Amazon и Netflix используют веб в качестве основного канала доставки своих услуг.
В письме Оззи есть мысль, которую разработчики не часто слышат от топменеджеров крупной корпорации:

Сложность убивает. Она высасывает соки из разработчиков, затрудняет планирование, сборку и тестирование продуктов, порождает проблемы в части безопасности и служит причиной горьких разочарований пользователей и администраторов.

Прежде всего, следует принять во внимание, что в 2005 году крупные ИТкомпании были всем сердцем влюблены в умопомрачительно сложные технологии типа SOAP, WS-* и XML. В то время еще не было слова «микросервисы» и 
даже на горизонте не просматривалась простая технология, которая позволила бы 
разработчикам справиться с проблемами составления асинхронной композиции 
простых служб для получения более сложных, не упуская из виду такие аспекты, 
как обработка ошибок, задержки, безопасность и эффективность.
Для моей группы облачных программных продуктов письмо Оззи стало призывом не заниматься ерундой, а сосредоточиться на придумывании простой модели 
программирования, которая позволит создавать крупномасштабные асинхронные 
архитектуры Интернет-служб для работы с большими объемами данных. После 
многих фальстартов на нас наконец снизошло озарение: взяв за основу интерфейсы Iterable/Iterator для синхронных коллекций, мы могли бы получить пару интерфейсов для представления потоков асинхронных событий и применять всем 
хорошо знакомые операции над последовательностями – map, filter, scan, zip, 
groupBy и другие – к преобразованию и комбинированию асинхронных потоков 
данных. Так летом 2007 года родилась идея Rx. В процессе реализации мы поняли, 
что необходимо как-то управлять конкурентностью и временем и с этой целью 
обобщили идею исполнителей в Java, дополнив ее виртуальным временем и кооперативной многозадачностью.
После напряженной двухлетней работы, когда были опробованы и отвергнуты 
разнообразные проектные решения, 18 ноября 2009 года мы наконец выпустили 

Предисловие

первую версию Rx.NET. Вскоре после этого мы перенесли Rx на Microsoft.Phone.
Reactive для Windows Phone 7 и приступили к реализации Rx на таких языках, как 
JavaScript и C++, а заодно поэкспериментировали с Ruby и Objective-C.
Внутри Майкрософт первым пользователем Rx стал Джафар Хусейн (Jafar 
Husain), эту технологию он взял с собой, когда перешел в Netflix в 2011 году. 
Джафар всячески пропагандировал Rx в компании и в конце концов полностью 
переделал клиентскую часть пользовательского интерфейса Netflix на основе 
асинхронной обработки потоков. И, к счастью для всех нас, он заразил своим энтузиазмом Бена Кристенсена, занимавшегося в Netflix разработкой API промежуточного уровня. В 2012 году Бен начал работать над RxJava и в начале 2013 разместил весь код на Github, сделав его открытым. Еще одним из ранних приверженцев 
Rx в Майкрософт был Пол Беттс (Paul Betts), позже он перешел в Github и убедил 
коллег, в т. ч. Джастина Спар-Саммерса (Justin Spahr-Summers) реализовать и выпустить ReactiveCocoa для Objective-C, что и произошло весной 2012.
Поскольку Rx завоевывал популярность в отрасли, мы убедили отдел Microsoft 
Open Tech раскрыть код Rx.NET, это случилось осенью 2012. Вскоре после этого я 
ушел из Майкрософт, основал компанию Applied Duality и посвятил все свое время тому, чтобы сделать Rx стандартным кросс-языковым и кросс-платформенным 
API для асинхронной обработки потоков данных в режиме реального времени.
К 2016 году популярность Rx стремительно возросла, как и число пользователей. Весь трафик, проходящий через Netflix API, обрабатывается RxJava. То же 
можно сказать о библиотеке обеспечения отказоустойчивости Hystrix, лежащей 
в основе всего внутреннего трафика службы, и сопутствующих реактивных библиотеках RxNetty и Mantis. Сейчас Netflix работает над полностью реактивным 
сетевым стеком для связывания всех внутренних служб, пересекающих границы 
процессов и машин. RxJava нашла также весьма полезные применения в экосистеме Android. Компании SoundCloud, Square, NYT, Seatgeek используют RxJava 
в своих приложениях и вносят вклад в разработку дополнительной библиотеки 
RxAndroid. Такие поставщики NoSQL-решений, как Couchbase и Splunk, также 
предлагают основанные на Rx интерфейсы к уровню доступа к данным. Среди других Java-библиотек, воспринявших RxJava, упомянем Camel Rx, Square Retrofit 
и Vert.x. В сообществе JavaScript широко распространена библиотека RxJS, лежащая в основе популярного каркаса Angular 2. Сообщество поддерживает сайт 
http://reactivex.io/, на котором можно найти информацию о реализациях Rx на 
многих языках, а также фантастические камешковые диаграммы с пояснениями, 
созданные Дэвидом Гроссом (@CallHimMoorlock).
С самого начала проект Rx развивался в соответствии с потребностями сообщества разработчиков и при его активном участии. В оригинальной реализации Rx 
в .NET упор был сделан, прежде всего, на преобразовании асинхронных потоков 
событий и использовании асинхронных перечислимых объектов в ситуациях, где 
требуется противодавление. Поскольку в Java нет языковой поддержки асинхронного ожидания, сообщество дополнило типы Observer и Observable концепцией 
реактивного вытягивания и добавило интерфейс Producer. Благодаря усилиям 

Предисловие

многих разработчиков реализация RxJava получилась весьма изощренной и в высшей степени оптимизированной.
Несмотря на то что детали RxJava несколько отличаются от других реализаций Rx, библиотека все равно ориентирована специально на разработчиков, стремящихся выжить в прекрасном новом мире распределенной обработки данных в 
реальном времени и сконцентрироваться на эссенциальной, а не акцидентальной 
сложности, высасывающей из нас все соки. Эта книга содержит глубокое и подробное изложение концепций и принципов использования Rx вообще и RxJava 
в частности, написанное двумя авторами, которые потратили бессчетное количество часов на реализацию RxJava и применение ее к реальным задачам. Если вам 
нужна «реактивность», то лучшего способа, чем купить книгу, не придумаешь.

– Эрик Мейер, основатель и президент
компании Applied Duality, Inc.

Вступление

Для.кого.написана.эта.книга

Книга ориентирована на Java-программистов средней и высокой квалификации. 
Читатель должен свободно владеть языком Java, но предварительное знакомство с реактивным программированием не предполагается. Многие описываемые 
концепции относятся к функциональному программированию, но знакомство 
с ним также не обязательно. Особенно полезна книга будет двумя группам 
программистов.
• Профессионалы, которым нужно повысить производительность сервера 
или сделать код для мобильных устройств более удобным для сопровождения. Если вы из их числа, то найдете здесь идеи и готовые решения реальных проблем, а также практические советы. А RxJava тогда следует считать 
просто еще одним инструментом, который книга поможет освоить.
• Любопытные разработчики, которые слыхали о реактивном программировании или конкретно о RxJava и хотели бы понять, что это такое. Если вы 
относите себя к этой категории и не планируете немедленно использовать 
преимущества RxJava в производственном коде, то книга заметно обогатит 
ваш багаж знаний.
Наконец, это книга станет подспорьем для практикующего архитектора программного обеспечения. RxJava оказала сильное влияние на общую архитектуру 
целых систем, поэтому знать об этой технологии полезно. Но даже если вы только 
начинаете путешествие в мир программирования, все равно попробуйте прочитать 
первые главы, в которых объяснены основы. Понятия преобразования и композиции 
универсальны и не являются спецификой реактивного программирования.

Несколько.слов.от.Бена.Кристенсена

В 2012 году я работал над новой архитектурой Netflix API. По ходу дела стало 
ясно, что для достижения поставленных целей необходимо включить конкурентность и асинхронные сетевые запросы. Исследуя различные подходы, я столкнулся с Джафаром Хусейном (https://github.com/jhusain), который попытался заинтересовать меня технологией Rx, с которой познакомился, работая в Майкрософт. 
В то время я довольно сносно владел техникой конкурентного программирования, 

Вступление

но размышлял о нем в императивных терминах и преимущественно с точки зрения Java, поскольку именно программированием на Java зарабатывал себе на хлеб.
Поэтому мне трудно было воспринять пропагандируемый Джафаром подход 
из-за его функциональной ориентированности, и я не поддавался на его убеждения. За этим последовали месяцы споров и дискуссий, архитектура системы становилась все более зрелой, а мы с Джафаром снова и снова встречались у доски, 
пока я, наконец, не врубился в теоретические принципы, а затем и не оценил элегантность и эффективность подходов, предлагаемых Rx.
Мы решили включить модель программирования Rx в Netflix API и в конечном итоге создали реализацию на Java, которую назвали RxJava, следуя заданным 
Майкрософт образцам: Rx.Net и RxJS.
За примерно три года, когда создавалась библиотека RxJava, по большей части 
на GitHub, в виде открытого кода, я имел удовольствие работать с растущим сообществом и соавторами, каковых было 120 с лишним, и вместе нам удалось превратить RxJava в зрелый продукт, используемый во многих системах как на стороне сервера, так и на стороне клиента. Он собрал больше 15 000 звезд на GitHub, 
что позволило войти в первые 200 проектов (https://github.com/search?p=11&q= 
stars:%3E1&s=stars&type=Repositories) и занять третье место среди проектов на Java 
(https://github.com/search?l=Java&p=1&q=stars:%3E1&s=stars&type=Repositories).
Джордж Кэмпбелл (George Campbell), Аарон Талл (Aaron Tull) и Мэтт Джекобс 
(Matt Jacobs) из Netflix много сделали для превращения RxJava из первых сборок 
в то, чем она является теперь. В частности, им проект обязан добавлением lift, 
Subscriber, противодавления и поддержки других языков на базе JVM. Дэвид 
Карнок (David Karnok) присоединился к проекту позже, но уже обошел меня по 
числу фиксаций и написанных строк кода. Ему проект в значительной мере обязан 
своим успехом, а теперь он возглавил его.
Хочу поблагодарить Эрика Мейера, который создал Rx во время работы в Майкрософт. С тех пор как он уволился оттуда, я урывками общался с ним в Netflix, 
когда трудился над RxJava, а теперь счастлив работать вместе в Facebook. Я считаю большой честью обсуждать с ним различные вопросы у доски и учиться у него. 
С таким наставником, как Эрик, поднимаешься на новый уровень мышления.
Попутно мне приходилось много раз выступать на конференциях с докладами 
о RxJava и реактивном программировании, и я повстречал много людей, которые 
помогли мне узнать о коде и архитектуре куда больше, чем я мог бы достичь 
собственными силами.
Netflix оказала мне феноменальное содействие, позволяя тратить время и силы 
на этот проект и выделив специалистов для написания технической документации, – сам я с этим точно не справился бы. Проект с открытым исходным кодом 
такого масштаба и качества никогда не стал бы успешным, если бы у меня не было 
возможности заниматься им в рабочее время и привлекать людей с разными знаниями и умениями.
Первая глава книги представляет собой мою попытку объяснить, почему реактивное программирование вообще полезно и как конкретно в RxJava реализованы 
общие принципы.

Доступ онлайн
849 ₽
В корзину