[Java] Асинхронное выполнение задач с использованием Redis и Spring Boot (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В этой статье мы рассмотрим, как использовать Spring Boot 2.x и Redis для выполнения асинхронных задач, а полный код продемонстрирует шаги, описанные в этом посте.Spring/Spring BootSpring — самый популярный фреймворк для разработки Java приложений. Таким образом, Spring имеет одно из крупнейших сообществ с открытым исходным кодом. Кроме того, Spring предоставляет обширную и актуальную документацию, которая охватывает внутреннюю работу фреймворка и примеры проектов в своем блоге, а на StackOverflow более 100 тысяч вопросов и ответов. Вначале Spring поддерживал только конфигурацию на основе XML, и из-за этого был подвержен множеству критических замечаний. Позже Spring представила конфигурацию на основе аннотаций, которая изменила все. Spring 3.0 была первой версией, которая поддерживала конфигурацию на основе аннотаций. В 2014 году была выпущена Spring Boot 1.0, полностью изменившая наш взгляд на экосистему фреймворка Spring. Более подробное описание истории Spring можно найти здесь. RedisRedis — одна из самых популярных NoSQL баз данных в памяти. Redis поддерживает разные типы структур данных. Redis поддерживает различные типы структур данных, например Set, Hash table, List, простую пару ключ-значение — это лишь некоторые из них. Задержка вызова Redis составляет менее миллисекунд, поддержка набора реплик и т. д. Задержка операции Redis составляет менее миллисекунд, что делает ее еще более привлекательной для сообщества разработчиков.Почему асинхронное выполнение задачиТипичный вызов API состоит из пяти этапов:
- Выполние одного или нескольких запросов к базе данных (RDBMS / NoSQL)
- Одна или несколько операций системы кэширования (In-Memory, Distributed и т. д.)
- Некоторые вычисления (это может быть обработка данных при выполнении некоторых математических операций)
- Вызов других служб (внутренних / внешних)
- Планирование выполнения одной или нескольких задач на более позднее время или немедленно, но в фоновом режиме
Задачу можно запланировать на более позднее время по многим причинам. Например, счет-фактура должен быть создан через 7 дней после создания или отгрузки заказа. Точно так же уведомления по электронной почте не нужно отправлять немедленно, поэтому мы можем отложить их. Имея в виду эти реальные примеры, иногда нам нужно выполнять задачи асинхронно, чтобы сократить время ответа API. Например, если мы удалим более 1K записей за один раз, и если мы удалим все эти записи в одном вызове API, то время ответа API наверняка увеличится. Чтобы сократить время ответа API, мы можем запустить задачу в фоновом режиме, которая удалит эти записи. Отложенная очередьКаждый раз, когда мы планируем запуск задачи в определенное время или через определенный интервал, мы используем задания cron, которые запланированы на определенное время или интервал. Мы можем запускать задачи по расписанию, используя различные инструменты, такие как crontab в стиле UNIX, Chronos, если мы используем фреймворки Spring, тогда речь идет об аннотации Scheduled ❤️. Большинство заданий cron просматривают записи о том, когда должно быть предпринято определенное действие, например, поиск всех поставок по истечении семи дней, по которым не были созданы счета. Большинство таких механизмов планирования страдают проблемами масштабирования, когда мы сканируем базы данных, чтобы найти соответствующие строки/записи. Во многих случаях это приводит к полному сканированию таблицы, которое работает очень медленно. Представьте себе случай, когда одна и та же база данных используется приложением реального времени и этой системой пакетной обработки. Поскольку она не является масштабируемый, нам понадобится какая-то масштабируемая система, которая может выполнять задачи в заданное время или интервал без каких-либо проблем с производительностью. Есть много способов масштабирования таким образом, например, запускать задачи в пакетном режиме или управлять задачами для определенного подмножества пользователей/регионов. Другой способ — запустить конкретную задачу в определенное время без зависимости от других задач, например безсерверной функции. Отложенная очередь может использоваться в тех случаях, как только таймер достигнет запланированного времени работа будет вызвана. Имеется множество систем/программного обеспечения для организации очередей, но очень немногие из них, например SQS, предоставляют функцию, которая обеспечивает задержку на 15 минут, а не произвольную задержку, такую как 7 часов или 7 дней и т. д.RqueueRqueue — это брокер сообщений, созданный для платформы Spring, который хранит данные в Redis и предоставляет механизм для выполнения задачи с любой указанной задержкой. Rqueue поддерживается Redis, поскольку Redis имеет некоторые преимущества перед широко используемыми системами очередей, такими как Kafka, SQS. В большинстве серверных приложений веб-приложений Redis используется для хранения данных кеша или для других целей. В настоящее время 8,4% веб-приложений используют базу данных Redis.Как правило, для очереди мы используем либо Kafka/SQS, либо некоторые другие системы, эти системы приносят дополнительные накладные расходы в разных измерениях, например, финансовые затраты, которые можно уменьшить до нуля с помощью Rqueue и Redis.Помимо затрат, если мы используем Kafka, нам необходимо выполнить настройку инфраструктуры, обслуживание, то есть больше операций, так как большинство приложений уже используют Redis, поэтому у нас не будет накладных расходов на операции, на самом деле можно использовать тот же сервер/кластер Redis с Rqueue. Rqueue поддерживает произвольную задержку
Доставка сообщенийRqueue гарантирует доставку сообщения хотя бы раз, так как длинные данные не теряются в базе данных. Подробнее об этом читайте на странице Введение в Rqueue.Инструменты, которые нам понадобятся:
- Любая IDE
- Gradle
- Java
- Redis
Мы собираемся использовать Spring Boot для простоты. Мы создадим проект Gradle с помощью инициализатора Spring Boot по адресу https://start.spring.io/.Из зависимостей нам понадобятся:
- Spring Data Redis
- Spring Web
- Lombok и некоторые другие
Структура каталогов/папок показана ниже:
Мы собираемся использовать библиотеку Rqueue для выполнения любых задач с произвольной задержкой. Rqueue — это основанный на Spring исполнитель асинхронных задач, который может выполнять задачи с любой задержкой, он построен на библиотеке обмена сообщениями Spring и поддерживается Redis.Мы добавим зависимость spring boot starter для Rqueue com.github.sonus21:rqueue-spring-boot-starter:2.0.0-RELEASE с помощью кода:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.github.sonus21:rqueue-spring-boot-starter:2.0.0-RELEASE'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
Нам нужно включить функции Redis Spring Boot. В целях тестирования мы также включим WEB MVC.Обновите файл application как:
@SpringBootApplication
@EnableRedisRepositories
@EnableWebMvc
public class AsynchronousTaskExecutorApplication {
public static void main(String[] args) {
SpringApplication.run(AsynchronousTaskExecutorApplication.class, args);
}
}
Добавлять задачи с помощью Rqueue очень просто. Нам нужно аннотировать метод с помощью RqueueListener. В RqueuListenerаннотации есть несколько полей, которые можно настроить в зависимости от варианта использования. Установите deadLetterQueueдля отправки задач в другую очередь. В противном случае задача будет отброшена в случае неудачи. Мы также можем установить, сколько раз задача должна быть повторена, используя поле. numRetriesСоздайте файл Java с именем MessageListenerи добавьте несколько методов для выполнения задач:
@Component
@Slf4j
public class MessageListener {
@RqueueListener(value = "${email.queue.name}") (1)
public void sendEmail(Email email) {
log.info("Email {}", email);
}
@RqueueListener(value = "${invoice.queue.name}") (2)
public void generateInvoice(Invoice invoice) {
log.info("Invoice {}", invoice);
}
}
Нам понадобится классы Email и Invoiceдля хранения данных электронной почты и счетов-фактур соответственно. Для простоты у классов будет только небольшое количество полей.Invoice.java:
import lombok.Data;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Invoice {
private String id;
private String type;
}
Email.java:
import lombok.Data;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Email {
private String email;
private String subject;
private String content;
}
Отправка задач в очередьЗадачу можно отправить в очередь с помощью RqueueMessageSender bean-компонента. У которого есть несколько методов для постановки задачи в очередь в зависимости от сценария использования, используйте один из доступных методов. Для простых задач используйте enqueue, для отложенных задач используйте enqueueIn.Нам нужно автоматически подключить RqueueMessageSenderили использовать внедрение на основе конструктора для внедрения этих bean-компонентов.Вот как создать контроллер для тестирования. Мы планируем создать счет-фактуру, который нужно будет выполнить через 30 секунд. Для этого мы отправим задачу с задержкой 30000 (миллисекунд) в очереди счетов. Кроме того, мы постараемся отправить электронное письмо, которое может выполняться в фоновом режиме. Для этого мы добавим два метода GET, sendEmail и generateInvoice, мы также можем использовать POST.
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class Controller {
private @NonNull RqueueMessageSender rqueueMessageSender;
@Value("${email.queue.name}")
private String emailQueueName;
@Value("${invoice.queue.name}")
private String invoiceQueueName;
@Value("${invoice.queue.delay}")
private Long invoiceDelay;
@GetMapping("email")
public String sendEmail(
@RequestParam String email, @RequestParam String subject, @RequestParam String content) {
log.info("Sending email");
rqueueMessageSender.enqueu(emailQueueName, new Email(email, subject, content));
return "Please check your inbox!";
}
@GetMapping("invoice")
public String generateInvoice(@RequestParam String id, @RequestParam String type) {
log.info("Generate invoice");
rqueueMessageSender.enqueueIn(invoiceQueueName, new Invoice(id, type), invoiceDelay);
return "Invoice would be generated in " + invoiceDelay + " milliseconds";
}
}
Добавим в файл application.properties следующие строки:
email.queue.name=email-queue
invoice.queue.name=invoice-queue
# 30 seconds delay for invoice
invoice.queue.delay=300000
Теперь мы можем запустить приложение. После успешного запуска приложения вы можете просмотреть результат по этой ссылке.В журнале мы видим, что задача электронной почты выполняется в фоновом режиме:
Ниже приведено расписание выставления счетов через 30 секунд:http://localhost:8080/invoice?id=INV-1234&type=PROFORMA
ЗаключениеТеперь мы можем планировать задачи с помощью Rqueue без большого объёма вспомогательного кода! Были приведены основные соображения по настройке и использованию библиотеки Rqueue. Следует иметь в виду одну важную вещь: независимо от того, является ли задача отложенной задачей или нет, по умолчанию предполагается, что задачи необходимо выполнить как можно скорее.Полный код этого поста можно найти в репозитории на GitHub. Дополнительное чтениеSpring Boot: Creating Asynchronous Methods Using @Async AnnotationSpring and Threads: AsyncDistributed Tasks Execution and Scheduling in Java, Powered by Redis
===========
Источник:
habr.com
===========
===========
Автор оригинала: Sonu Kumar
===========Похожие новости:
- [JavaScript, Программирование, C#, Rust] Вышла версия 1.0 библиотеки для управления секс-игрушками Buttplug
- [Java] Мониторинг и профилирование Spring Boot приложения (перевод)
- [Разработка веб-сайтов, Программирование, Java] Пять причин, по которым следует использовать Apache Wicket (перевод)
- [PHP, Python, JavaScript, Управление разработкой] Эволюция команды разработки
- [JavaScript, Разработка мобильных приложений, Разработка под Android] Cordova. Quick start
- [JavaScript, Разработка мобильных приложений, Разработка игр, ReactJS] Как я разработал мобильную игру на Android с использованием React.js и выложил её в Google Play Store
- [Мессенджеры, JavaScript, API, Социальные сети и сообщества] Botsman: новая платформа для разработки Telegram-ботов
- [JavaScript, Разработка игр] Как внезапно для себя написать игру за день…
- [Разработка веб-сайтов, JavaScript, Node.JS] Обзор npm 7
- [JavaScript, Программирование, Дизайн мобильных приложений, TypeScript] Автоматизируем локализацию макетов в Figma
Теги для поиска: #_java, #_spring, #_spring_boot, #_redis, #_asynchronous_task, #_java
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 03:32
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В этой статье мы рассмотрим, как использовать Spring Boot 2.x и Redis для выполнения асинхронных задач, а полный код продемонстрирует шаги, описанные в этом посте.Spring/Spring BootSpring — самый популярный фреймворк для разработки Java приложений. Таким образом, Spring имеет одно из крупнейших сообществ с открытым исходным кодом. Кроме того, Spring предоставляет обширную и актуальную документацию, которая охватывает внутреннюю работу фреймворка и примеры проектов в своем блоге, а на StackOverflow более 100 тысяч вопросов и ответов. Вначале Spring поддерживал только конфигурацию на основе XML, и из-за этого был подвержен множеству критических замечаний. Позже Spring представила конфигурацию на основе аннотаций, которая изменила все. Spring 3.0 была первой версией, которая поддерживала конфигурацию на основе аннотаций. В 2014 году была выпущена Spring Boot 1.0, полностью изменившая наш взгляд на экосистему фреймворка Spring. Более подробное описание истории Spring можно найти здесь. RedisRedis — одна из самых популярных NoSQL баз данных в памяти. Redis поддерживает разные типы структур данных. Redis поддерживает различные типы структур данных, например Set, Hash table, List, простую пару ключ-значение — это лишь некоторые из них. Задержка вызова Redis составляет менее миллисекунд, поддержка набора реплик и т. д. Задержка операции Redis составляет менее миллисекунд, что делает ее еще более привлекательной для сообщества разработчиков.Почему асинхронное выполнение задачиТипичный вызов API состоит из пяти этапов:
Доставка сообщенийRqueue гарантирует доставку сообщения хотя бы раз, так как длинные данные не теряются в базе данных. Подробнее об этом читайте на странице Введение в Rqueue.Инструменты, которые нам понадобятся:
Мы собираемся использовать библиотеку Rqueue для выполнения любых задач с произвольной задержкой. Rqueue — это основанный на Spring исполнитель асинхронных задач, который может выполнять задачи с любой задержкой, он построен на библиотеке обмена сообщениями Spring и поддерживается Redis.Мы добавим зависимость spring boot starter для Rqueue com.github.sonus21:rqueue-spring-boot-starter:2.0.0-RELEASE с помощью кода: dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'com.github.sonus21:rqueue-spring-boot-starter:2.0.0-RELEASE' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' } } @SpringBootApplication
@EnableRedisRepositories @EnableWebMvc public class AsynchronousTaskExecutorApplication { public static void main(String[] args) { SpringApplication.run(AsynchronousTaskExecutorApplication.class, args); } } @Component
@Slf4j public class MessageListener { @RqueueListener(value = "${email.queue.name}") (1) public void sendEmail(Email email) { log.info("Email {}", email); } @RqueueListener(value = "${invoice.queue.name}") (2) public void generateInvoice(Invoice invoice) { log.info("Invoice {}", invoice); } } import lombok.Data;
@Data @AllArgsConstructor @NoArgsConstructor public class Invoice { private String id; private String type; } import lombok.Data;
@Data @AllArgsConstructor @NoArgsConstructor public class Email { private String email; private String subject; private String content; } @RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired)) @Slf4j public class Controller { private @NonNull RqueueMessageSender rqueueMessageSender; @Value("${email.queue.name}") private String emailQueueName; @Value("${invoice.queue.name}") private String invoiceQueueName; @Value("${invoice.queue.delay}") private Long invoiceDelay; @GetMapping("email") public String sendEmail( @RequestParam String email, @RequestParam String subject, @RequestParam String content) { log.info("Sending email"); rqueueMessageSender.enqueu(emailQueueName, new Email(email, subject, content)); return "Please check your inbox!"; } @GetMapping("invoice") public String generateInvoice(@RequestParam String id, @RequestParam String type) { log.info("Generate invoice"); rqueueMessageSender.enqueueIn(invoiceQueueName, new Invoice(id, type), invoiceDelay); return "Invoice would be generated in " + invoiceDelay + " milliseconds"; } } email.queue.name=email-queue
invoice.queue.name=invoice-queue # 30 seconds delay for invoice invoice.queue.delay=300000 Ниже приведено расписание выставления счетов через 30 секунд:http://localhost:8080/invoice?id=INV-1234&type=PROFORMA ЗаключениеТеперь мы можем планировать задачи с помощью Rqueue без большого объёма вспомогательного кода! Были приведены основные соображения по настройке и использованию библиотеки Rqueue. Следует иметь в виду одну важную вещь: независимо от того, является ли задача отложенной задачей или нет, по умолчанию предполагается, что задачи необходимо выполнить как можно скорее.Полный код этого поста можно найти в репозитории на GitHub. Дополнительное чтениеSpring Boot: Creating Asynchronous Methods Using @Async AnnotationSpring and Threads: AsyncDistributed Tasks Execution and Scheduling in Java, Powered by Redis =========== Источник: habr.com =========== =========== Автор оригинала: Sonu Kumar ===========Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 03:32
Часовой пояс: UTC + 5