Neste artigo, daremos uma olhada em como usar Spring Boot 2.xe Redis para realizar tarefas assíncronas, e o código completo demonstrará as etapas descritas nesta postagem.
Spring / Spring Boot
Spring é a estrutura mais popular para desenvolver aplicativos Java. Como tal, Spring tem uma das maiores comunidades de código aberto. Além disso, o Spring fornece documentação extensa e atualizada que cobre o funcionamento interno da estrutura e exemplos de projetos em seu blog, e há mais de 100.000 perguntas e respostasno StackOverflow .
No início, o Spring suportava apenas configuração baseada em XML e estava sujeito a muitas críticas por causa disso. Posteriormente, o Spring introduziu a configuração baseada em anotações que mudou tudo. Spring 3.0 foi a primeira versão a suportar configuração baseada em anotação. Em 2014, Spring Boot 1.0 foi lançado , mudando completamente a forma como olhamos para o ecossistema do framework Spring. Uma descrição mais detalhada da história do Spring pode ser encontrada aqui .
Redis
Redis é um dos bancos de dados NoSQL em memória mais populares. O Redis oferece suporte a diferentes tipos de estruturas de dados. O Redis oferece suporte a vários tipos de estruturas de dados, como Set, Hash table, List, pares chave-valor simples, para citar apenas alguns. A latência da chamada do Redis é inferior a milissegundos, suporte para conjunto de réplicas e assim por diante. A latência da operação do Redis é inferior a milissegundos, tornando-o ainda mais atraente para a comunidade de desenvolvedores.
Por que a execução assíncrona de tarefas
Uma chamada API típica tem cinco etapas:
Executando uma ou mais consultas de banco de dados (RDBMS / NoSQL)
Uma ou mais operações de sistema de cache (In-Memory, Distribuído, etc.)
Alguns cálculos (pode ser processamento de dados durante a execução de algumas operações matemáticas)
Ligar para outros serviços (interno / externo)
,
. , - 7 . , .
, , API. , 1K , API, API . API, , .
, , cron, . , , crontab UNIX, Chronos, Spring, Scheduled ❤️.
cron , , , , . , , /. , . , . , - , - . , , /. — , . , . / , , SQS, , 15 , , 7 7 . .
Rqueue
Rqueue — , 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
Agora podemos agendar tarefas usando o Rqueue sem muitos códigos adicionais! As considerações básicas para configurar e usar a biblioteca Rqueue foram fornecidas. É importante ter em mente que, independentemente de a tarefa ser uma tarefa pendente ou não, o padrão é assumir que as tarefas precisam ser concluídas o mais rápido possível.
O código completo desta postagem pode ser encontrado no repositório do GitHub .
Leitura adicional
Spring Boot: Criando métodos assíncronos usando @Async Annotation
Execução e programação de tarefas distribuídas em Java, desenvolvido por Redis