SpringBoot + JobRunr で Web アプリとワーカープロセスを分離する方法
概要
これまで は同じプロセス内で Web アプリと JobRunr ワーカーを起動させていました
これだとワーカーだけをスケールアウトさせたい場合に不便です
今回は Web アプリとワーカーを別々のプロセスで起動する方法を紹介します
環境
macOS 26.4.1
openjdk 26.0.1
SpringBoot 4.0.6
jasypt-spring-boot 4.0.4
jackson-databind 2.21.2
jobrunr 8.6.1
gradle 9.5.1
VSCode 1.121.0
MySQL 9.6.0
Redis 8.6.3
Web アプリケーション
Web アプリ専用のアプリケーションを作成します
こちらは SpringBoot が必要なので @SpringBootApplication にします
また専用のプロパティ (application.properties と application-web.properties) を読み込むので profiles に web を指定します
vim src/main/java/com/example/demo/AccessingDataMysqlApplication.java
package com. example. demo;
import org. springframework. boot. autoconfigure. SpringBootApplication;
import org. springframework. boot. builder. SpringApplicationBuilder;
import org. springframework. boot. context. properties. ConfigurationPropertiesScan;
import com. ulisesbocchio. jasyptspringboot. annotation. EnableEncryptableProperties;
@EnableEncryptableProperties
@ConfigurationPropertiesScan
@SpringBootApplication
public class AccessingDataMysqlApplication {
public static void main ( String[ ] args) {
new SpringApplicationBuilder ( AccessingDataMysqlApplication. class ) . profiles ( "web" ) . run ( args) ;
}
}
Web アプリケーション用設定ファイル
今回は application.properties だけを読み込むので application-web.properties は作成しなくて OK です
もし Web アプリにだけ必要な設定や application.properties の設定を上書きしたい場合には application-web.properties を作成して設定しましょう
vim src/main/resources/application.properties
spring.application.name = demo
spring.jpa.hibernate.ddl-auto = update
spring.jpa.show-sql = true
spring.datasource.url = jdbc:mysql://${MYSQL_HOST:127.0.0.1}:3306/mydatabase
spring.datasource.username = ENC(bFMupckSRHJ/9QmXd1EVTw==)
spring.datasource.password = ENC(QFCt95vHHcJpgm8oKhghkJoEknQv3tF0)
spring.data.redis.host = localhost
spring.data.redis.port = 6379
app.jobrunr.background-job-server.enabled = false
jasypt.encryptor.algorithm = PBEWithMD5AndDES
jasypt.encryptor.iv-generator-classname = org.jasypt.iv.NoIvGenerator
jasypt.encryptor.password = ${JASYPT_PASSWORD:default_password}
ワーカーアプリケーション
@SpringBootApplication は不要です
JobRunr として動かすために SpringApplicationBuilder を使い定義します
こうすることで SpringBoot の Bean 機能などが使えます
profiles には worker を指定し application-worker.properties を使えるようにします
vim src/main/java/com/example/demo/WorkerApplication.java
package com. example. demo;
import org. springframework. boot. builder. SpringApplicationBuilder;
public class WorkerApplication {
public static void main ( String[ ] args) {
new SpringApplicationBuilder ( AccessingDataMysqlApplication. class ) . profiles ( "worker" ) . run ( args) ;
}
}
ワーカーアプリケーション用設定ファイル
ワーカー専用の設定ファイルを作成します
Web アプリとして動作しないための設定を記載します
application.properties の設定を上書きします
vim src/main/resources/application-worker.properties
spring.main.web-application-type = none
app.jobrunr.background-job-server.enabled = true
Bean に設定を注入するためのクラス
application-worker.properties の値は自動的に読み込まれます
しかし Bean には読み込まれないのでプロパティファイルから設定を取得し Bean に注入します
vim src/main/java/com/example/demo/config/JobRunrBackgroundJobServerProperties.java
package com. example. demo. config;
import org. springframework. boot. context. properties. ConfigurationProperties;
@ConfigurationProperties ( prefix = "app.jobrunr.background-job-server" )
public class JobRunrBackgroundJobServerProperties {
private boolean enabled = false ;
public boolean isEnabled ( ) {
return enabled;
}
public void setEnabled ( boolean enabled) {
this . enabled = enabled;
}
}
そしてこの設定を使って JobRunr の設定 (Bean) を作成します
vim src/main/java/com/example/demo/config/JobRunrConfig.java
package com. example. demo. config;
import javax. sql. DataSource;
import org. jobrunr. configuration. JobRunr;
import org. jobrunr. scheduling. JobScheduler;
import org. jobrunr. server. JobActivator;
import org. jobrunr. storage. StorageProvider;
import org. jobrunr. storage. StorageProviderUtils. DatabaseOptions;
import org. jobrunr. storage. sql. mysql. MySqlStorageProvider;
import org. springframework. context. ApplicationContext;
import org. springframework. context. annotation. Bean;
import org. springframework. context. annotation. Configuration;
@Configuration
public class JobRunrConfig {
@Bean
StorageProvider storageProvider ( DataSource dataSource) {
return new MySqlStorageProvider ( dataSource, DatabaseOptions. CREATE) ;
}
@Bean
JobActivator jobActivator ( ApplicationContext applicationContext) {
return applicationContext: : getBean;
}
@Bean
JobScheduler jobScheduler ( StorageProvider storageProvider, JobActivator jobActivator,
JobRunrBackgroundJobServerProperties jobRunrBackgroundJobServerProperties) {
return JobRunr. configure ( ) . useStorageProvider ( storageProvider) . useJobActivator ( jobActivator)
. useBackgroundJobServerIf ( jobRunrBackgroundJobServerProperties. isEnabled ( ) ) . initialize ( )
. getJobScheduler ( ) ;
}
}
サービスなどの設定
これは前回 と同様です
build.gradle の修正
以下の設定を追記します
Web アプリケーションだけを起動する設定とビルドする設定、そしてワーカーアプリケーションだけを起動しビルドする設定を追加します
tasks. named ( 'bootJar' ) {
archiveClassifier = 'web'
mainClass = 'com.example.demo.AccessingDataMysqlApplication'
}
tasks. named ( 'bootRun' , org. springframework. boot. gradle. tasks. run. BootRun) {
mainClass = 'com.example.demo.AccessingDataMysqlApplication'
}
def webBootJar = tasks. named ( 'bootJar' , org. springframework. boot. gradle. tasks. bundling. BootJar)
tasks. register ( 'workerBootRun' , org. springframework. boot. gradle. tasks. run. BootRun) {
group = 'application'
description = 'Runs the worker process (non-web) using WorkerApplication.'
mainClass = 'com.example.demo.WorkerApplication'
classpath = sourceSets. main. runtimeClasspath
}
tasks. register ( 'workerBootJar' , org. springframework. boot. gradle. tasks. bundling. BootJar) {
group = 'build'
description = 'Builds the executable worker jar.'
archiveClassifier = 'worker'
mainClass = 'com.example.demo.WorkerApplication'
classpath = sourceSets. main. runtimeClasspath
targetJavaVersion = webBootJar. get ( ) . targetJavaVersion
dependsOn tasks. named ( 'classes' )
}
tasks. named ( 'assemble' ) {
dependsOn tasks. named ( 'workerBootJar' )
}
動作確認
./gradlew clean && ./gradlew bootRun --args='--jasypt.encryptor.password=xxx'
./gradlew clean && ./gradlew workerBootRun -Dspring-boot.run.mainClass=com.example.demo.WorkerApplication --args='--jasypt.encryptor.password=xxx'
Web アプリケーション、ワーカーアプリケーションそれぞれのプロセスで立ち上げます
これで curl で動作確認するとワーカー側のロギング処理がワーカー側の起動したターミナルだけに表示されることが確認できます
ビルド
jar を作成するには以下の通りです
これで build/libs 配下に各種 jar が作成できます
jar を実行するには以下のようにします
最後に
JobRunr で Web アプリケーションとワーカーアプリケーションを分離させる方法を紹介しました
もしワーカーを増やしたい場合はワーカーの jar だけ追加で起動すれば OK です
試しに複数起動してみましたが2つのワーカーが処理することはなかったので大丈夫だと思います