この記事では、Spring Boot 2.xとRedisを使用して非同期タスクを実行する方法を見ていきます。完全なコードは、この投稿で概説されている手順を示しています。
春/春のブーツ
Spring は、Javaアプリケーションを開発するための最も一般的なフレームワークです。そのため、Springには最大のオープンソースコミュニティの1つがあります。さらに、Springは、フレームワークの内部動作とサンプルプロジェクトをカバーする広範囲で最新のドキュメントをブログで提供しており、 StackOverflowには10万を超える 質問と回答が あります。
当初、SpringはXMLベースの構成のみをサポートしており、このため多くの批判を受けていました。Springは後に、すべてを変更する注釈ベースの構成を導入しました。Spring 3.0は、注釈ベースの構成をサポートする最初のバージョンでした。2014年にSpringBoot 1.0がリリースさ れ、Springフレームワークエコシステムの見方が完全に変わりました。春の歴史のより詳細な説明は ここにあります。
Redis
Redisは、最も人気のあるNoSQLインメモリデータベースの1つです。Redisは、さまざまなタイプのデータ構造をサポートしています。Redisは、Set、Hashテーブル、List、単純なキーと値のペアなど、さまざまなタイプのデータ構造をサポートしています。Redis呼び出しの待ち時間はミリ秒未満、レプリカセットのサポートなどです。Redis操作の待ち時間はミリ秒未満であるため、開発者コミュニティにとってさらに魅力的です。
非同期タスク実行の理由
一般的なAPI呼び出しには、次の5つのステップがあります。
1つ以上のデータベースクエリの実行(RDBMS / NoSQL)
1つ以上のキャッシングシステム操作(インメモリ、分散など)
いくつかの計算(これは、いくつかの数学的な操作を実行している間のデータ処理である可能性があります)
他のサービスの呼び出し(内部/外部)
,
. , - 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
これで、多くのヘルプコードなしで、Rqueueを使用してタスクをスケジュールできます。Rqueueライブラリを設定および使用するための基本的な考慮事項が提供されています。覚えておくべき重要なことの1つは、タスクが保留中のタスクであるかどうかに関係なく、デフォルトでは、タスクをできるだけ早く完了する必要があると想定することです。
この投稿の完全なコードは 、GitHubのリポジトリにあり ます。
追加の読み物
Spring Boot:@AsyncAnnotationを使用した非同期メソッドの作成
Redisを利用したJavaでの分散タスクの実行とスケジューリング