введение
Самое простое определение реактивного программирования: Реактивное программирование — это программирование с использованием асинхронных потоков данных. Будь то среда реактивного программирования, представленная в Spring5, или реактивный поток, интегрированный в java9, можно увидеть тень реактивного программирования. Можно сказать, что реактивное программирование представляет собой направление программирования будущего.
Реактивное программирование по своей сути является неблокирующим, автоматически запуская следующее действие, когда данные готовы, вместо ожидания завершения данных. Эта идея в сочетании с асинхронным программированием позволяет нам унифицировать модель многопоточности и снизить стоимость многопоточного программирования, одновременно повышая производительность всей системы.
Текущие бизнес-сценарии Xianyu достаточно сложны, однако блокирующее программирование по-прежнему широко используется, а процессы каждого бизнес-сценария выполняются последовательно и синхронно. Его самая большая проблема — большое количество потоков, ожидающих завершения ввода-вывода (логирование, RPC-вызовы, HTTP-запросы и т. д.). Ввиду этого Xianyu представила RxJava 2.0 как среду реактивного программирования для асинхронного преобразования приложений. В настоящее время домашняя страница рыбного пруда, список сообщений и информация о рыбном пруду в приложении были асинхронно преобразованы и запущены.
Практика реактивного асинхронного программирования
Асинхронное программирование отличается от традиционного блочного программирования.Различие может быть выражено следующей диаграммой, где C обозначает вычислительную задачу, а I обозначает задачу ввода-вывода. Исходный поток выполнил все задачи вычислений и операций ввода-вывода, а теперь задачи вычислений и задачи ввода-вывода разделены. Преимущество этого заключается в том, что ЦП уделяет внимание только вычислительным задачам. Теоретически, несколько потоков ядер ЦП могут удовлетворить все вычислительные задачи, что значительно снижает накладные расходы на переключение потоков.
Модель резьбы за каркасом Rxjava - это эволюция модели резьбы. Перед введением Rxjava традиционная Java имела собственную многопоточную структуру (Исполнитель) и асинхронное будущее. Проблема с ними является то, что
-
Пулы потоков не могут быть унифицированы. Разработчики могут определять пулы потоков в своих сценариях.
-
переключение контекста. По мере увеличения количества потоков неизбежно будет увеличиваться переключение контекстов потоков.
-
Асинхронный метод Future по-прежнему является методом ожидания блокировки.
Преимущество RxJava в сочетании с полностью асинхронным программированием заключается в том, что
-
Использование потоков значительно улучшено. Когда потоку необходимо выполнить операцию блокировки, он вовремя переключается, чтобы не занимать поток в течение длительного времени, и весь процесс неблокируется.
-
RxJava объединяет модель пула потоков. Мы можем выбрать соответствующую модель планирования потоков в соответствии с различными сценариями.
-
Становится возможной экстремальная многопоточная модель. Теоретически для выполнения всех вычислительных задач требуется всего несколько потоков процессорных ядер, а это означает, что накладные расходы, вызванные переключением потоков, практически исключены.
Модернизация приложения
Реактивное полностью асинхронное программирование по своей природе отказывается блокироваться, и любая точка блокировки может привести к снижению производительности. А если серьезно, то если мы будем контролировать количество потоков, когда задачи накапливаются из-за блокировки, приложение будет влиять на онлайн-сервис по мере увеличения количества накопленных задач. В настоящее время в приложении Xianyu есть 4 типа узких мест.
-
Журнал приложений.
-
HTTP-запрос.
-
РПЦ звонки.
-
Кэш чтения и записи.
Журналы в Xianyu используются не только как средство аномального вывода, но и как основной метод статистики данных. Потому что производительность журнала очень важна. Хотя и log4j, и logback предоставляют асинхронные методы, по сути они основаны на блокировках. log4j2 — это новое поколение lock-free асинхронной системы логирования на основе LMAX Disruptor, в многопоточных программах его пропускная способность примерно в 10 раз выше, чем у log4j и logback.
Однако HTTP, RPC и чтение и запись кэша должны быть преобразованы в чисто асинхронный режим: поток освобождается, когда происходит запрос, а остальная часть бизнес-процесса продолжает выполняться в новом потоке после завершения запроса. .
парадигма исполнения
Подводя итог сценам в Сяньюй, мы можем выделить три парадигмы исполнения, ниже мы кратко покажем эти три парадигмы. Для простоты задействованные операции ввода-вывода абстрагируются функцией.
серийный запросВозьмите обычный сценарий электронной коммерции в качестве примера, чтобы просмотреть сведения о продуктах, которые я купил. В бизнес-процессе вам нужно сначала запросить сведения о заказе, затем получить продукт из сведений о заказе и, наконец, запросить сведения о продукте в соответствии с продуктом.
//查订单
Flowable<Order> orderFlow = Flowable.fromCallable(() -> queryOrder(orderId));
//查商品
Flowable<Item> itemFlow = orderFlow.flatMap(order -> Flowable.fromCallable(() -> queryItem(order.getId())));
скопировать код
одновременные запросыЧасто в описании товара есть дополнительная информация, например просмотры страниц и содержание сообщений. Просмотры и комментарии не зависят друг от друга, но оба зависят от найденной информации о продукте.
Flowable<Detail> detailFlow = itemFlow.flatMap(item -> {
//浏览量
Flowable<Long> pvFlow = Flowable.fromCallable(() -> queryItemPv(item.getId()));
//留言
Flowable<Comment> commentFlow = Flowable.fromCallable(() -> queryItemComment(item.getId()));
//浏览,留言,商品共同组成detail
return Flowable.zip(pvFlow,commentFlow,(pv,comment) -> buildItemDetail(item,pv,comment));
});
скопировать код
обновить кешПопулярные списки продуктов часто означают высокий одновременный доступ, и мы можем кэшировать эти данные, чтобы уменьшить нагрузку на базу данных. Однако успешное кэширование или нет не влияет на этот запрос (сбой кеша приводит к тому, что следующий запрос все равно идет к БД, а данные этого запроса все равно возвращаются пользователю). Кэши обновлений по сути представляют собой класс операций, выполняющих некоторые дополнительные операции (кэширование, уведомление пользователей, логирование и т. д.) после выполнения запроса, и успех или неудача этих дополнительных операций никак не влияет на основной процесс.
//更新缓存,doOnNext不会对流的结果造成任何影响,只是触发一个操作
detailFlow.doOnNext(detail -> cache(detail));
скопировать код
Следует подчеркнуть, что все методы в приведенном выше потоке соответствуют операции ввода-вывода (RPC, кэш-чтение и запись и т. д.), и эти операции ввода-вывода должны быть реализованы полностью асинхронно (вы не можете ждать завершения ввода-вывода). , но активно просыпаются после завершения ввода-вывода). К счастью, уже есть некоторые сторонние библиотеки, которые помогут нам выполнить эту асинхронность ввода-вывода.
Результаты модернизации
Мы провели серию тестов производительности на модифицированном интерфейсе и сравнили выполнение с блокировкой и отзывчивые чистые асинхронные методы по трем аспектам: интерфейс rt, количество потоков и загрузка процессора.
rtПоскольку мы добавили параллельные операции в асинхронном режиме, снижение rt неизбежно, и снижение rt составляет около 50%. Когда количество запросов в секунду достигает 650, традиционный метод блокировки rt взлетает, и сервис становится недоступным; отзывчивый чисто асинхронный метод rt относительно стабилен и начинает значительно расти, когда число запросов в секунду достигает 850.
ПотокиБлокирующий режим выполнения связан с тем, что поток будет ожидать завершения ввода-вывода, когда произойдет ввод-вывод, а в асинхронном режиме поток напрямую освобождается, поэтому эффективность использования потока в асинхронном режиме значительно выше. Следующие результаты тестов также показывают, что количество потоков в асинхронном режиме было относительно стабильным; в режиме блокировки потоки исчерпываются, когда количество запросов в секунду достигает 650, что означает, что новые запросы будут напрямую отклонены.
CPUПоскольку мы увеличиваем параллелизм в асинхронном режиме, загрузка ЦП должна быть выше, чем в блочном режиме, и результаты тестов также показывают это. Однако, когда количество запросов в секунду достигает 650, служба становится недоступной в режиме блокировки, поэтому максимальная загрузка ЦП может достигать только около 75 %, тогда как в асинхронном режиме ЦП может достигать 97 %.
Суммировать
В этой статье представлен статус приложения адаптивного программирования в Xianyu.Мы выбираем RxJava в качестве среды адаптивного программирования и выбираем список сообщений Xianyu, домашнюю страницу рыбного пруда и страницу сведений о рыбном пруду, чтобы преобразовать и проверить производительность. Тестовые данные показывают, что в сценарии домашней страницы группового чата Xianyu пропускная способность всей системы может быть увеличена примерно на 30%, а скорость передачи данных уменьшена на 50%.
В настоящее время реактивное чистое асинхронное программирование все еще находится в зачаточном состоянии в Xianyu, и наша модель пула потоков все еще не идеальна (на данный момент невозможно полностью устранить точки блокировки). Далее мы попытаемся достичь окончательной модели многопоточности, и возможные точки трансформации включают
-
Устранение блокирующих точек.
-
Несколько потоков процессорных ядер используются для планирования всех вычислительных задач.
-
Базовая модель потока ввода-вывода унифицирована. Теперь все операции ввода-вывода (RPC, HTTP, кеш) поддерживают свои собственные пулы потоков, теоретически эти пулы потоков можно унифицировать.
связаться с нами
Если у вас есть какие-либо вопросы или исправления по содержанию текста, пожалуйста, сообщите нам об этом.
Техническая команда Xianyu — это небольшая и мощная инженерно-техническая команда. Мы не только фокусируемся на эффективном решении бизнес-задач, но в то же время продвигаем передовую практику разрушения разделения труда в стеке технологий (унификация моделей и языков программирования android/iOS/Html5/Server) и технология компьютерного зрения на мобильных терминалах. В качестве инженера-программиста в технической команде Xianyu у вас есть возможность продемонстрировать все свои таланты и мужество, доказав, что развитие технологий является движущей силой изменения образа жизни во всей эволюции продукта и решении проблем пользователей.
Доставка резюме: guicai.gxy@alibaba-inc.com
Распознавайте QR-код и осваивайте передовые технологии