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:
Exécution d'une ou plusieurs requêtes de base de données (SGBDR / NoSQL)
Une ou plusieurs opérations du système de mise en cache (en mémoire, distribuées, etc.)
Certains calculs (il peut s'agir d'un traitement de données lors de l'exécution de certaines opérations mathématiques)
Appeler d'autres services (internes / externes)
,
. , - 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
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
Exécution et planification de tâches distribuées en Java, optimisées par Redis