-->

Spring Boot - infinite loop service

2020-06-18 11:03发布

问题:

I want to build a headless application which will query the DB in infinite loop and perform some operations in certain conditions (e.g. fetch records with specific values and when found launch e-mail sending procedure for each message).

I want to use Spring Boot as a base (especially because of Actuator to allow expose health-checks), but for now I used Spring Boot for building REST web-services.

Is there any best practices or patterns to follow when building infinite loop applications ? Does anyone tried to build it based on Spring Boot and can share with me his architecture for this case ?

Best regards.

回答1:

What I'm using is a message broker and a consumer put at the spring boot application to do the job.



回答2:

Do not implement an infinite loop yourself. Let the framework handle it using its task execution capabilities:

@Service
public class RecordChecker{

    //Executes each 500 ms
    @Scheduled(fixedRate=500)
    public void checkRecords() {
        //Check states and send mails
    }
}

Don't forget to enable scheduling for your application:

@SpringBootApplication
@EnableScheduling
public class Application {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class);
    }
}

See also:

  • Scheduling Tasks


回答3:

There are several options. My approach is to start a loop on an ApplicationReadyEvent, and abstract away the loop logic into an injectable service. In my case it was a game loop, but this pattern should work for you as well.

package com.ryanp102694.gameserver;

import com.ryanp102694.gameserver.service.GameProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class GameLauncher implements ApplicationListener<ApplicationReadyEvent> {
    private static Logger logger = LoggerFactory.getLogger(GameLauncher.class);

    private GameProcessor gameProcessor;

    @Autowired
    public GameLauncher(GameProcessor gameProcessor){
        this.gameProcessor = gameProcessor;
    }

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        logger.info("Starting game process.");
        gameProcessor.start();
        while(gameProcessor.isRunning()){
            logger.debug("Collecting user input.");
            gameProcessor.collectInput();
            logger.debug("Calculating next game state.");
            gameProcessor.nextGameState();
            logger.debug("Updating clients.");
            gameProcessor.updateClients();
        }
        logger.info("Stopping game process.");
        gameProcessor.stop();
    }
}