⇧ 時代が変わっても変わらないもの...
というわけで、Javaについてです。
レッツトライ~。
JavaのQuartzでJobを更新するのが厄介な件
JavaのQuartzというライブラリで、バッチ処理ができるということを知ったのですが、Quartzの仕組みとしては、
⇧ 上図のように、
- Job
- Trigger
- Job Store
の三位一体で、バッチ処理のインスタンスを作成して、Thread Poolにスレッドとして登録しておいて、Triggerで指定しておいた日時が来たら実行されるような構造になってますと。
で、バッチ処理のインスタンスを作成するのが、Quartz Schedulerというもので、
When the factory creates the Scheduler instance, it also passes the Scheduler an instance of an org.quartz.core.QuartzSchedulerResources.
The QuartzSchedulerResources contains, among others things, a ThreadPool instance that provides a pool of worker threads that are responsible for executing jobs. In Quartz, a ThreadPool is represented by the org.quartz.spi.ThreadPool interface (because Quartz was invented before JDK 1.5, it needed to create its own ThreadPool classto ensure backward compatibility, Quartz still utilizes its THReadPool instead of Java's) and includes a concrete implementation called org.quartz.simpl.SimpleThreadPool.
The SimpleThreadPool has a fixed number of worker threads and doesn't shrink or grow based on load. Figure 4.6 shows the sequence of steps that the framework undergoes during startup as it relates to threads.
https://flylib.com/books/en/2.65.1/thread_usage_in_quartz.html
⇧ このあたりのインスタンスは、QuartzというライブラリがJVM(Java Virtual Machine)のクラスローダーとかで読み込まれた時に生成されるということかと。
Worker Threadsっていうものは、
What Are Quartz Worker Threads?
Quartz doesn't process your jobs on the main thread. If it did, it would severely reduce the scalability of the application.
Instead, Quartz delegates the thread-management responsibilities to a separate component.
For the generic Quartz setup, which most users employ, the SimpleThreadPool class handles thread management.
The SimpleThreadPool creates a number of WorkerThread instances that are responsible for processing a job on a separate thread.
The WorkerThread is an inner class defined within the SimpleThreadPool class and is essentially a thread.
The number of WorkerThreads that are created and the priority for these threads are specified by the configuration settings in the quartz.properties file or are passed into the factory.
https://flylib.com/books/en/2.65.1/thread_usage_in_quartz.html
⇧ アプリケーションmainスレッド上のプロセスとして、バッチ処理をすることはできないけど別スレッドで管理します、という仕組みの結果、生成されたスレッド群ということらしい。
で、Worker Threadsは、Thread Poolにプールされていくバッチ処理群のことになると思うのだけど、
When the QuartzSchedulerThread asks the ThreadPool to run a JobRunShell instance, the ThreadPool checks to see if a worker thread is available. If all the configured worker threads are busy, the ThreadPool waits until one becomes available.
When a worker thread is available and a JobRunShell is waiting to be executed, the worker thread calls the run() method on the JobRunShell class.
https://flylib.com/books/en/2.65.1/thread_usage_in_quartz.html
⇧ Thread PoolがWorker Threadを監視をしていて、Worker Threadが実行可能な状態になったタイミング(Triggerで指定した日時など)で、QuartzSchedulerThreadに通知して、QuartzSchedulerThreadがWorker Threadに実行のゴーサインを出し、Worker ThreadはJobRunShellのrunメソッドを呼び出すことで、バッチ処理が実行されるってことになりますと。
ちなみに、Javaのプログラミングというのは、mainスレッドの1スレッドで動いてるのが基本っぽいのですが、
Quartzというライブラリのように、mainスレッドとは別にスレッド管理します、のような仕組みを導入すると、
⇧ 上記のように、mainスレッドは別にスレッドが増えることになり、「マルチスレッド」のような状況が発生するということですかね。
Quartzの全体的な流れとしては、
⇧上図のような感じになりますと。
長々と脱線しましたが、Quartzのドキュメントを確認すると、
Job Persistence
-
The design of Quartz includes a JobStore interface that can be implemented to provide various mechanisms for the storage of jobs.
-
With the use of the included JDBCJobStore, all Jobs and Triggers configured as "non-volatile" are stored in a relational database via JDBC.
-
With the use of the included RAMJobStore, all Jobs and Triggers are stored in RAM and therefore do not persist between program executions - but this has the advantage of not requiring an external database.
http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/introduction.html
⇧ Jobを永続化したい場合に、
の2つの選択肢を用意してくれていますと。
今回は、「JDBC(Java Database Conectivity)」に対応したデータベースのケースで考えていくのですが、その前に、Quartzが用意してくれてるテーブルについては、
⇧ 上記のGitHubで確認ができるのですが、PostgreSQLの場合だと、
⇧ のようなテーブルを作成して、Jobなどに関するデータが保存されることになるのですが、ここでJobを更新したいとなった時に問題になるのが、
⇧ 上記サイト様のように、Quartzでメソッドを用意はしてくれているのですが、更新したいJobを確かめるための検索っぽいことはできない模様。
検索とかしたい場合は、
Create, Update and Delete Jobs Dynamically in Quartz
https://xebiaww.wordpress.com/2012/06/14/create-update-and-delete-jobs-dynamically-in-quartz/
⇧ Quartzで用意されてるテーブルから引っ張てこれるような仕組みを自分で作る必要があるみたいね。
話が脱線しましたが、バッチ処理とかって、テーブルのレコードに対する集計や一括更新など定期的なタイミング(毎日深夜0:00など決まった時間)で処理をするようなケースで利用されることが多いとは思いますと。
一方で、テーブルのレコードに対する逐次処理など不定期なタイミング(メルマガの発信など、配信時間の変更が頻繁に発生しうるような状況)でも使われるケースはあり、その場合は、Jobの数が膨大になってくると思うので、Jobを特定できるようなカラムをテーブルに追加して保持しておいたほうが良さ気ですね。
今回はこのへんで。