Exécution de tâches asynchrones à l'aide de Redis et Spring Boot

Dans cet article, nous verrons comment utiliser Spring Boot 2.x et Redis pour effectuer des tâches asynchrones, et le code complet montrera les étapes de cet article.





Spring / Spring Boot

Spring  est le framework le plus populaire pour le dĂ©veloppement d'applications Java. En tant que tel, Spring possède l'une des plus grandes communautĂ©s open source. En outre, Spring fournit une documentation complète et Ă  jour qui couvre le fonctionnement interne du framework et des exemples de projets sur son blog, et il y a plus de 100000  questions et rĂ©ponsessur  StackOverflow





Au dĂ©but, Spring ne prenait en charge que la configuration basĂ©e sur XML et a fait l'objet de nombreuses critiques Ă  cause de cela. Spring a ensuite introduit une configuration basĂ©e sur les annotations qui a tout changĂ©. Spring 3.0 a Ă©tĂ© la première version Ă  prendre en charge la configuration basĂ©e sur les annotations. En 2014, Spring Boot  1.0 est sorti  , changeant complètement la façon dont nous regardons l'Ă©cosystème du framework Spring. Une description plus dĂ©taillĂ©e de l'histoire du printemps peut ĂŞtre trouvĂ©e  ici





Redis

Redis est l'une des bases de données NoSQL en mémoire les plus populaires. Redis prend en charge différents types de structures de données. Redis prend en charge différents types de structures de données telles que Set, Hash table, List, simples paires clé-valeur pour n'en nommer que quelques-unes. La latence des appels Redis est inférieure à quelques millisecondes, la prise en charge des jeux de réplicas, etc. La latence des opérations Redis est inférieure à quelques millisecondes, ce qui la rend encore plus attractive pour la communauté des développeurs.





Pourquoi une exécution de tâche asynchrone





Un appel API typique comporte cinq Ă©tapes:





  1. Exécution d'une ou plusieurs requêtes de base de données (SGBDR / NoSQL)





  2. Une ou plusieurs opérations du système de mise en cache (en mémoire, distribuées, etc.)





  3. Certains calculs (il peut s'agir d'un traitement de données lors de l'exécution de certaines opérations mathématiques)





  4. Appeler d'autres services (internes / externes)





  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





Maintenant, nous pouvons planifier des tâches en utilisant Rqueue sans beaucoup de code supplémentaire! Les considérations de base pour la configuration et l'utilisation de la bibliothèque Rqueue ont été fournies. Une chose importante à garder à l'esprit est que, que la tâche soit une tâche en attente ou non, la valeur par défaut est de supposer que les tâches doivent être terminées dès que possible.





Le code complet de cet article se trouve dans le rĂ©fĂ©rentiel  sur  GitHub





Lecture supplémentaire

Spring Boot: création de méthodes asynchrones à l'aide de l'annotation @Async





Ressort et threads: Async





Exécution et planification de tâches distribuées en Java, optimisées par Redis
























































All Articles