像我们做项目写接口的时候,一定要考虑接口的并发性,要是写的接口提供第三方系统来调用,更需要保证自己提供的接口不会被调崩。有的并发性高的系统,在同一时刻或者同一小时间段,会有大量流量涌入,这时候你的接口不做相应的处理直接被调,很容易发生超时然后导致接口崩溃。我们可以用线程池来解决这一痛点。
1、写一个接口 controller 类
package com.riemann.springbootdemo.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; /** * @author riemann * @date 2019/10/31 23:06 */ @Controller public class ConcurrentThreadCallController { @RequestMapping(value = "/ConcurrentThreadCall/sayHello",method = RequestMethod.GET) @ResponseBody public String sayHello(String name) { return "Hello " + name; } }我们用 postman 来模拟10个线程
这里的并发数 你模拟的是多少就填多少 下面就是没做任何处理的响应时间,我累加了下是 1156 ms
2、对线程池的参数优化后
package com.riemann.springbootdemo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.ThreadPoolExecutor; /** * @author riemann * @date 2019/10/31 22:50 */ @Configuration public class ConcurrentThreadGlobalConfig { @Bean public ThreadPoolTaskExecutor defaultThreadPool() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //核心线程数目 executor.setCorePoolSize(4); //指定最大线程数 executor.setMaxPoolSize(100); //队列中最大的数目 executor.setQueueCapacity(50); //线程名称前缀 executor.setThreadNamePrefix("DefaultThreadPool_"); //rejection-policy:当pool已经达到max size的时候,如何处理新任务 //CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行 //对拒绝task的处理策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //线程空闲后的最大存活时间 executor.setKeepAliveSeconds(60); //加载 executor.initialize(); return executor; } }我统计了下,用了线程池后耗时 828 ms
这里我是模拟的10个线程来调用该接口,那要是有1000个线程来调用呢?那你需要根据自己的机器的性能来配置好核心线程数目、最大线程数、队列中最大的数目等相应的参数,这样可以起到限流的作用,防止高峰流量把接口给调崩;还可以提升接口的响应性能,继而提升系统的性能。