Often services need some kind of "cronjobs" or rather scheduled tasks. Spring supports scheduling out of the box.
Very often, each scheduled tasks should only be executed once, but in typical microservice-setups there are multiple instances of a service running.
There are different approaches to execute a task only once.
- Trigger the job "from the outside", i.e. via HTTP-Request. A load balancer makes sure only one instance works on this job. This is great to leverage existing schedulers, e.g. Kubernetes CronJobs
- Use distributed locking, e.g. via SchedLock. This solution is independent of it's platform (although it requires something to manage the lock, e.g. a database)
Kubernetes provides a lot of solutions for typical problems of distributed services. One of those problems is leader election. Fortunately, Spring Cloud Kubernetes provides a kubernetes-based leader-election implementation.
Using leader-election and spring-scheduling, it's very easy to implement a "run exactly one scheduled task" solution.
Each solution has its pros and cons.
Task scheduling based on kubernetes leader election has the advantage that it does not have any external dependencies (locks in a database, an HTTP-endpoint that needs to be secured).
To run the example, apply the example.yaml
manifest to deploy the application, e.g. to minikube, but you can use any cluster you like.
kubectl --context minikube apply -f example.yaml
Then view logs any verify only one pod runs the job.
kubectl --context minikube logs --prefix -f -l app=scheduler