Execução de tarefa assíncrona usando Redis e Spring Boot

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:





  1. Executando uma ou mais consultas de banco de dados (RDBMS / NoSQL)





  2. Uma ou mais operações de sistema de cache (In-Memory, Distribuído, etc.)





  3. Alguns cálculos (pode ser processamento de dados durante a execução de algumas operações matemáticas)





  4. Ligar para outros serviços (interno / externo)





  5. ,    





. , - 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.





, :





  1. IDE





  2. Gradle 





  3. Java





  4. Redis 





 Spring Boot .  Gradle Spring Boot  https://start.spring.io/.





:  





  1. Spring Data Redis





  2. Spring Web





  3. 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





Spring and Threads: Async





Execução e programação de tarefas distribuídas em Java, desenvolvido por Redis
























































All Articles