DEV Community

Anh Trần Tuấn
Anh Trần Tuấn

Posted on • Originally published at tuanh.net on

Scheduling Jobs in Microservices and Illustrative Examples

1. Using the @Scheduled Annotation

Spring Boot enables scheduling of regular jobs via the @Scheduled annotation. This annotation can be applied to methods within bean classes, which are annotated with @Component, @Service, or @Configuration.

@Service
public class AService {
    @Scheduled(cron = "0 0 * * * *")
    public void performScheduledTask() {
        // Logic cho cron job
    }
}
Enter fullscreen mode Exit fullscreen mode

In order to schedule tasks, you must first enable scheduling within your Spring Boot application. This is achieved by annotating a configuration class with @EnableScheduling.

"0 0 * * *" is a cron expression used to schedule tasks on a recurring basis. Here's a detailed breakdown of each part of this expression:

Seconds : 0

Specifies that the task will start at the 0th second of every minute.

Minutes : 0

Specifies that the task will start at the 0th minute of every hour.

Hours : *

Specifies that the task will run every hour. The asterisk (*) means "every possible value," so the task will run at every hour of the day.

Day of Month : *

Specifies that the task will run every day of the month. The asterisk (*) means "every possible value," so the task will run on every day of the month.

Month : *

Specifies that the task will run every month. The asterisk (*) means "every possible value," so the task will run every month of the year.

Day of Week : *

Specifies that the task will run every day of the week. The asterisk (*) means "every possible value," so the task will run every day of the week.

In summary: The cron expression "0 0 * * * *" will execute the task every day at 00:00:00 (midnight). This means the task will run precisely at midnight every day.

If you encounter any difficulties when creating cron job expressions, you can refer to crontab.guru

When you define a module across multiple pods and use the @Scheduled annotation, the annotation will be triggered multiple times because each pod is essentially a separate application. They are stateless with respect to each other. Therefore, if you want to use the @Scheduled annotation, ensure that there is only one instance of the module running at any given time.

2. Using the Task Scheduling Service

These services, Amazon CloudWatch Events and Google Cloud Scheduler, allow you to schedule your HTTP endpoints or functions to be triggered at specific interval

Below, I will demo a simple example, using Schedules in Amazon EventBridge of AWS.

Image

Image

Select the event you want to trigger. In this case, I've selected a lambda function. You can choose other triggers.

Image

Upon successful setup, a public function will be triggered to run a job at 10:10 AM on August 14, 2024.

Image

3. Using Kubernetes CronJobs

Kubernetes CronJobs offer a scheduling mechanism to run jobs at specified times or intervals within your Kubernetes cluster, which is ideal for microservices architectures.

apiVersion: batch/v1
kind: CronJob
metadata:
  name: test-job
  labels:
    test.ch/module: test-service
spec:
  schedule: "0 1 * * *"
  jobTemplate:
    spec:
      template:
        metadata:
          labels:
            sidecar.istio.io/inject: "false"
        spec:
          containers:
          - name: test-job
            image: gcr.io/test-repo/java8-commons
            imagePullPolicy: IfNotPresent
            env:
            - name: URI
              value: "http://test-service:8080/api/test-cronjob/run"
            args:
            - /bin/sh
            - -c
            - |             
              RESULT=$(curl -X POST -s -o /dev/null -I -w "%{http_code}" $URI 
              -H "Accept: application/json" 
              if [$RESULT -ne 200];
                then
                  >&2 echo "Receive $RESULT from test-service with api $URI"
                else
                  echo $RESULT
              fi
          restartPolicy: OnFailure
Enter fullscreen mode Exit fullscreen mode

YAML Breakdown

apiVersion : batch/v1

Specifies the API version for CronJobs in Kubernetes.

kind : CronJob

Indicates that this is a CronJob object.

metadata :

Contains metadata about the CronJob.

name : The unique name of the CronJob (test-job).

labels : Labels used to select and identify the CronJob.

spec:

Defines the specification of the CronJob.

schedule : The schedule on which the job will run. In this case, it's set to run at 1 AM every day.

jobTemplate : Specifies the template for the job that will be created by the CronJob.

spec : The specification of the job.

template : The pod template for the job.

metadata : Metadata for the pod.

labels : Labels for the pod, including a label to prevent Istio sidecar injection.

spec : The specification of the pod.

containers : A list of containers.

name : The name of the container (test-job).

image : The Docker image to use for the container.

imagePullPolicy : The policy for pulling the image.

envFrom : Specifies a secret to populate environment variables.

env : Defines additional environment variables.

args : The arguments to pass to the container.

A shell script that:

Sends an HTTP POST request to the specified URI.

Checks the HTTP response code and prints an error message if it's not 200.

restartPolicy: The policy for restarting the container.

This CronJob is configured to run a job every day at 1 AM. The job will create a pod that runs a container. The container will:

Send an HTTP POST request: The container will send an HTTP POST request to the URL specified in the URI environment variable.

Check the response code: A shell script will check the HTTP response code. If the response code is not 200 (OK), it will print an error message to standard error.

Restart policy: The container will be restarted if it fails.

In essence, this CronJob is designed to perform a daily task that involves sending an HTTP POST request and verifying the response.

Image

If you use GKE, you can search for 'test-cronjob' and get the result as above.

4. Conclude

In conclusion, the choice of an appropriate scheduling method hinges on your specific needs and the structure of the microservices system you're managing.

Thank you for reading, and we look forward to seeing you again.

Top comments (0)