简体   繁体   中英

Spring sync vs async rest controller

I try to see a difference between Spring synchronous REST Controller vs async version of same controller.

Each controller do the same thing : take a RequestBody and save it in a Mongo database.

@RestController
@RequestMapping ("/api/1/ticks")
public class TickController {

    @Autowired
    private TickManager tickManager;

    @RequestMapping (method = RequestMethod.POST)
    public ResponseEntity save(@RequestBody List<Tick> ticks) {
        tickManager.save(ticks);

        return new ResponseEntity(HttpStatus.OK);
    }

    @RequestMapping (value = "/async", method = RequestMethod.POST)
    public @ResponseBody Callable<ResponseEntity> saveAsync(@RequestBody List<Tick> ticks) {
        return () -> {
            tickManager.save(ticks);

            return new ResponseEntity(HttpStatus.OK);
        };
    }
}

The tickManager has only a dependency on a tickRepository and just do call to sub-layer.

The tickRepository is based on Spring Data Mongodb:

@Repository
public interface TickRepository extends MongoRepository<Tick, String> {}

I use Gatling to test those controllers. This is my scenario:

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._

class TicksSaveSyncSimulation extends Simulation {

  val rampUpTimeSecs = 20
  val testTimeSecs   = 5
  val noOfUsers      = 1000
  val minWaitMs      = 1000 milliseconds
  val maxWaitMs      = 3000 milliseconds

  val baseURL      = "http://localhost:9080"
  val requestName  = "ticks-save-sync-request"
  val scenarioName = "ticks-save-sync-scenario"
  val URI          = "/api/1/ticks"

  val httpConf = http.baseURL(baseURL)

  val http_headers = Map(
    "Accept-Encoding" -> "gzip,deflate",
    "Content-Type" -> "application/json;charset=UTF-8",
    "Keep-Alive" -> "115"
  )

  val scn = scenario(scenarioName)
    .repeat(100) {  
      exec(
        http(requestName)
          .post(URI)
          .headers(http_headers)
          .body(StringBody(
            """[{
              |  "type": "temperature",
              |  "datas": {}
              |}]""".stripMargin))
          .check(status.is(200))
      )
    }

  setUp(scn.inject(rampUsers(1000) over (1 seconds))).protocols(httpConf)
}

I tried several situations and the sync version always handle 2 times more request by second than the async version. When I increase the number of users the two versions crash.

I tried to override the taskExecutor for the async version with no more success:

@Configuration
public class TaskExecutorConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setMaxPoolSize(1000);
        taskExecutor.setThreadNamePrefix("LULExecutor-");
        taskExecutor.initialize();
        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }
}

I thought see a difference in favor of the async implementation. What am I doing wrong?

Your test looks to be flawed. It doesn't make any sense being non blocking at one end of the pipeline (here, your controllers), and being blocking at the other end ( tickManager.save really looks like a blocking call). You're just paying the extra cost of jumping into a ThreadPoolTaskExecutor .

Then, generally speaking, you won't gain anything from a non blocking architecture when all your tasks are very fast, like a tick. You can expect gains when some tasks take some longer time, so you don't want to waste resources (threads, CPU cycles) just waiting for those to complete, and you want to use them to perform other tasks in the meanwhile.

Regarding your Too many open files exception, you probably haven't properly tuned your OS for load testing, check relevant documentation . There's also a good chance that you're running your app and Gatling (and possibly your database too) on the same host, which is bad as they'll compete for resources.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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