简体   繁体   English

使用Java(Spring)从数据库安排任务的最佳方法

[英]Best way to schedule tasks from database using Java (Spring)

I'm looking for frameworks to schedule a set of tasks populated in the Database 我正在寻找框架来安排数据库中填充的一组任务

JPA entities look like this JPA实体看起来像这样

@Entity
class Task extends Model {
    @NotNull
    @Min(1L)
    @Column(name = "interval_ms", nullable = false)
    Integer interval

    @NotNull
    String payload  

    @NotNull
    Boolean enabled
}

@Entity
class TaskResult extends Model {
    @ManyToOne(optional = false)
    Task task

    @Column(nullable = false)
    Boolean result

    @Column(nullable = false)
    String message
}

tasks should be executed every interval defined in the "interval" field, result should be written into TaskResult table 应在“间隔”字段中定义的每个间隔执行任务,结果应写入TaskResult表

The purpose of task is to make a GET or POST request, so requests have to be pooled to avoid the situation when a lot of tasks start to execute in parallel. 任务的目的是发出GET或POST请求,因此必须将请求池化,以避免许多任务开始并行执行的情况。

I'm using spring boot. 我正在使用弹簧靴。

what are best practices here? 什么是最佳做法?

If you are using Spring Boot, you can use TaskExecutor bean and configure pool size http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html#scheduling-task-executor-usage Then use TaskScheduler to define, when the task should run. 如果您使用的是Spring Boot,则可以使用TaskExecutor bean并配置池大小http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html#scheduling-task-executor-用法然后使用TaskScheduler定义任务应在何时运行。 Event values for this parameter comes from database (ie. Object). 此参数的事件值来自数据库(即对象)。

Once I created scheduler but I used Quartz. 创建调度程序后,我使用了Quartz。 I created newJob 's, which was triggered every 1 minute (but you can use also miliseconds) and searched EmailQueue in database, if email was found, it tries to send it, when error occured with sending, he do not delete email in the queue and writes into the LOG table details about an error. 我创建了newJob ,它每1分钟触发一次(但您也可以使用毫秒),并在数据库中搜索EmailQueue,如果找到了电子邮件,它将尝试发送它,当发送发生错误时,他不会删除电子邮件排队并将有关错误的详细信息写入LOG表。 The scheduler (1 minute) was set up from database. 从数据库设置了调度程序(1分钟)。 In your case you should use: newJob(QuartzJob.class).withIntervalInMilliseconds 在您的情况下,您应该使用:newJob(QuartzJob.class).withIntervalInMilliseconds

http://quartz-scheduler.org/api/2.2.0/org/quartz/SimpleScheduleBuilder.html#withIntervalInMilliseconds(long) http://quartz-scheduler.org/api/2.2.0/org/quartz/SimpleScheduleBuilder.html#withIntervalInMilliseconds(long)

@Service
public class MyQuartz implements InitializingBean, DisposableBean {

    @Autowired
    StdSchedulerFactory stdSchedulerFactory;
    @Autowired
    TableConfiguration tableConfiguration;
    Scheduler sched = null;
    JobDetail job, job2;
    JobDetail[] jobs = new JobDetail[2];

    public void initIt() throws Exception {

        try {
            System.out.println("Shedulling a job...");
            sched = stdSchedulerFactory.getScheduler();
        } catch (SchedulerException e) {
            System.err.println("Could not create scheduler.");
            e.printStackTrace();
        }
        try {
            System.out.println("Starting scheduler");
            sched.start();
        } catch (SchedulerException e) {
            System.err.println("Could not start scheduler.");
            e.printStackTrace();
        }
        // define the job and tie it to our QuartzJob class
        job = newJob(QuartzJob.class).withIdentity("myJob", "group1").build();
        job2 = newJob(QuartzCronJob.class).withIdentity("myCronJob", "group2")
                .build();
        jobs[0] = job;
        // .. here I have more jobs ...
        // Trigger the job to run now, and then every 5 minutes

        Trigger trigger = newTrigger()
                .withIdentity("myTrigger", "group1")
                .startNow()
                .withSchedule(
                        simpleSchedule().withIntervalInMinutes(
                                tableConfiguration.getTimeInterval())
                                .repeatForever()).build();

        // ... more triggers also here
        // Tell quartz to schedule the job using our trigger
        try {
            sched.scheduleJob(job, trigger);
            System.out.println("..job schedulled.");
        } catch (SchedulerException e) {
            System.err.println("Could not schedulle a job.");
            e.printStackTrace();
        }

    }

    @Override
    public void destroy() throws Exception {

        try {
            System.out.println("Stopping scheduler...");
            for (int i = 0; i < jobs.length; i++) { // Destroying all jobs
                sched.deleteJob(jobs[i].getKey());
            }
            sched.shutdown(true); // Waiting for jobs to complete.
            System.out.println("...scheduler Terminated. Good Bye.");
        } catch (SchedulerException e) {
            System.err.println("ERROR, scheduler cannot be stopped.");
            e.printStackTrace();
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {

    }
}

and

@Service
@Transactional
public class QuartzCronJob implements Job {
    @Override
    public void execute(JobExecutionContext context)
            throws JobExecutionException {
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = new GregorianCalendar();
        String schedulled = sdf.format(calendar.getTime());

        System.out.println("LIST now " + schedulled);
        List<EmailQueue> emails = emailQueueDao.findAllForToday(schedulled);

        if (emails != null) {
            for (EmailQueue email : emails) {
                // Send email:
                try {
                    sendmail.sendNotification(email.getFrom(), email.getTo(),
                            email.getSubject(), email.getMessage(), "Sched.");
                    // Delete email from queue:
                    emailQueueDao.delete(email.getId());
                    System.out.println("Email sucessfully sent and deleted.");
                } catch (Exception e) {
                    sendmail.logEmail(LoggerSeverity.ERROR,
                            "Could not send schedulled email", "Sched.");
                    System.err.println("Could not send schedulled email");
                }
            }
        } 
        // ... more code here, this is just a working sample...
    }
}

My code is not using pooling, but I did not retrieved more than 3 emails from database as it run once per minute :) 我的代码未使用缓冲池,但由于数据库每分钟运行一次,所以我没有从数据库中检索到3封以上的电子邮件:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM