Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
spring boot java scheduler应该只为三个dyno执行一次';每天多少钱_Java_Spring_Multithreading_Spring Boot_Concurrency - Fatal编程技术网

spring boot java scheduler应该只为三个dyno执行一次';每天多少钱

spring boot java scheduler应该只为三个dyno执行一次';每天多少钱,java,spring,multithreading,spring-boot,concurrency,Java,Spring,Multithreading,Spring Boot,Concurrency,我有spring boot和java应用程序。在一天中的特定时间,它应该执行一个方法。因此,在生产服务器中,我们保留了4个dyno,由于4个dyno,它每天执行4次。所以我使用了缓存来获取日期。根据日期,我只尝试执行一次该方法,但仍执行了4次 @Scheduled(zone = "${scheduler.zone}", cron = "${scheduler.cron.job}") public void processScheduled() {

我有spring boot和java应用程序。在一天中的特定时间,它应该执行一个方法。因此,在生产服务器中,我们保留了4个dyno,由于4个dyno,它每天执行4次。所以我使用了缓存来获取日期。根据日期,我只尝试执行一次该方法,但仍执行了4次

  @Scheduled(zone = "${scheduler.zone}", cron = "${scheduler.cron.job}")
  public  void processScheduled() {

   
    synchronized(this) {
      LocalDate localDate = redisTemplate.getValue("DATE");
      if (localDate == null || LocalDate.now().isAfter(localDate)) {
        log.info("Entered process in SchedulerConfig");
        redisTemplate.putValue("DATE", LocalDate.now());
        schedulerService.processScheduled();
      }
    }
  }

上面的代码是在ConfigJava类中编写的

  • schedulerService.processScheduled();应每天仅触发一次,而与dyno的否无关。 有人能帮我吗

  • 我假设您使用的是Heroku Dynos,因此您的应用程序有4个独立的实例在生产环境中运行。由于有4个单独的实例,因此您使用的
    synchronized
    在这里没有什么用处。您的所有4个实例都将同时被调用,因此有可能所有实例都将
    redisTemplate.getValue(“DATE”)
    的值设置为非空。您需要一个具有集中实体的原子操作。Redis确实是一个集中的实体,但是
    redisTemplate.getValue(“DATE”)
    redisTemplate.putValue(“DATE”,LocalDate.now())
    不是一个原子操作。因此,很可能有4个实例调用
    redisTemplate.getValue(“日期”)
    并获取实际日期。因为所有4个都不是null,所以它们都将更新值,然后处理您的操作

    您应该尝试使用
    redisTemplate.delete(key)
    。这是一个原子操作,如果删除密钥,则返回true,否则返回false。因此,您的代码可能如下所示

    @Scheduled(zone = "${scheduler.zone}", cron = "${scheduler.cron.job}")
    public  void processScheduled() {
      
          boolean isDeleted= redisTemplate.delete("DATE"); // only one will get true, other will get false.
    
          if (isDeleted) {
            log.info("Entered process in SchedulerConfig");
          
            schedulerService.processScheduled();
    
            // sleep for some time and then update the date value
            redisTemplate.putValue("DATE", LocalDate.now());
    
          }
        
      }
    
    或者,可以在调用一段时间后使用@Scheduled更新日期值

    @Scheduled(zone = "${scheduler.zone}", cron = "${scheduler.flag.update.job}")
    public  void updateDateFlag() {
        redisTemplate.putValue("DATE", LocalDate.now());
    }
    

    当请求同时出现时,这可以正常工作。有些时候,dyno的间隔是秒,这一次它是第二次执行调度程序。是的,我还注意到,redistemplate.putValue in if是罪魁祸首。您需要在调用时间跨度之后填充日期标志。在设置日期值之前,您可以使用另一个@Scheduled或sleep一段时间。