异步请求

Servlet异步请求

为什么要实现Servlet异步请求

我们先来看一下一个请求到Tomcat是怎么处理的



一个请求到达Tomcat后,便会分配tomcat中的一个线程去处理这个请求,但是,Tomcat中的请求是有限的,如果业务请求耗时过长,导致Tomcat中的线程一直被占用,最终导致用户的请求无法被tomcat处理,严重影响业务,如果说一个请求到了业务层之后,可以释放掉Tomcat中的线程,那么就可以解决这个问题了,Servlet异步请求便是实现了这个功能,我么来简单的看一个demo

原生Servlet异步

@RestController@RequestMapping("async")public class AsyncController {    @Autowired    private AsyncService asyncService;    @RequestMapping("getStudent")    public void getStudent(Long id, HttpServletRequest request) {        asyncService.getAsyncStudent(id, request);    }}@Servicepublic class AsyncService {    @Autowired    private StudentDao studentDao;    private ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 8,            60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));    public void getAsyncStudent(Long id, HttpServletRequest request) {        // 异步请求,释放Tomcat线程        AsyncContext asyncContext = request.startAsync();        // 通过线程池创建异步任务,将耗时的操作放到线程中执行        executor.submit(new AsyncTask(asyncContext, id));    }    public class AsyncTask implements Runnable {        private AsyncContext asyncContext;        private Long id;        public AsyncTask(AsyncContext asyncContext, Long id) {            this.asyncContext = asyncContext;            this.id = id;        }        @Override        public void run() {            // 执行耗时操作            Student student = studentDao.getStudent(id);            // 获取response            ServletResponse response = asyncContext.getResponse();            // 直接将结果通过response返回            ResponseUtils.generatorResponse((HttpServletResponse) response, student);            // 请求完成            asyncContext.complete();        }    }}@Slf4jpublic class ResponseUtils {    public static final void generatorResponse(HttpServletResponse response, Object data) {        generatorResponseString(response, JSON.toJSONString(data));    }    public static final void generatorResponseString(HttpServletResponse response, String data) {        try {            response.setHeader("Pragma", "no-cache");            response.setDateHeader("Expires", 0);            response.setHeader("Cache-Control", "no-cache,no-store");            //json格式            response.setContentType("application/json;charset=UTF-8");            response.setStatus(HttpServletResponse.SC_OK);            response.getWriter().println(data);        } catch (Exception e) {            log.error("返回结果出现异常", e);        }    }}

通过示例我们发现,Servlet实现异步请求还是很简单的,第一步,我们只需要调用request.startAsync()将请求异步,然后执行业务请求获取对应的结果,最后将请求的结果通过response返回给客户端。

我们再来看一下Spring支持的异步请求

Spring异步请求

@RestController@RequestMapping("spring/async")public class SpringAsyncController {    @Autowired    private SpringAsyncService springAsyncService;    @RequestMapping("getStudent")    public DeferredResult getStudent(Long id) {        DeferredResult deferredResult = new DeferredResult<>();        springAsyncService.getAsyncStudent(id, deferredResult);        return deferredResult;    }}@Servicepublic class SpringAsyncService {    @Autowired    private StudentDao studentDao;    private ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 8,            60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));    public void getAsyncStudent(Long id, DeferredResult deferredResult) {        // 异步请求        executor.submit(() -> {            Student student = studentDao.getStudent(id);            // 将请求结果返回            deferredResult.setResult(student);        });    }}
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章