使用多线程提高REST服务器性能
阅读原文时间:2023年07月08日阅读:2

异步处理REST服务

1、使用Runnable异步处理Rest服务

释放主线程,启用副线程进行处理,副线程处理完成后直接返回请求

主要代码

import java.util.concurrent.Callable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
*
* @author hzc
*
*/
@RestController
public class AsyncController {

private Logger logger = LoggerFactory.getLogger(AsyncController.class);

@RequestMapping("/order")  
public Callable<String> order() throws InterruptedException {  
    logger.info("主线程开始");

    Callable<String> result = new Callable<String>() {

        @Override  
        public String call() throws Exception {  
            logger.info("副线程开始");  
            Thread.sleep(1000);  
            logger.info("副线程结束");  
            return "success";  
        }

    };  
    logger.info("主线程返回");  
    return result;

}  

}

2、使用DeferredResult异步处理Rest服务

释放主线程,启用副线程1进行前处理,副线程2进行后处理,副线程2处理完后返回请求

模拟业务场景

主线程调用副线程1进行业务处理,将任务放于消息队列,副线程2监听消息队列,并处理队列的任务,在使用DeferredResult获取队列返回的结果,返回给前端

Controller类

package com.maple.security.web.async;

import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

/**
*
* @author hzc
*
*/
@RestController
public class AsyncController {

private Logger logger = LoggerFactory.getLogger(AsyncController.class);

@Autowired  
private MockQueue mockQueue;

@Autowired  
private DeferredResultHolder deferredResultHolder;

@RequestMapping("/order")  
public DeferredResult<String> order() throws InterruptedException {  
    logger.info("主线程开始");

    String orderNumber = RandomStringUtils.randomNumeric(8);  
    mockQueue.setPlaceOrder(orderNumber);

    DeferredResult<String> result = new DeferredResult<>();  
    deferredResultHolder.getMap().put(orderNumber, result);  
    logger.info("主线程返回");  
    return result;

}  

}

模拟消息队列类

package com.maple.security.web.async;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
*
* @author hzc
*
*/
@Component
public class MockQueue {

private Logger logger = LoggerFactory.getLogger(MockQueue.class);

// 生成下单  
private String placeOrder;

// 完成下单  
private String completeOrder;

public String getPlaceOrder() {  
    return placeOrder;  
}

public void setPlaceOrder(String placeOrder) {  
    new Thread(() -> {  
        logger.info("接到下单请求");  
        try {  
            Thread.sleep(1000);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        this.completeOrder = placeOrder;  
        logger.info("下单请求处理完毕," + placeOrder);  
    }).start();

}

public String getCompleteOrder() {  
    return completeOrder;  
}

public void setCompleteOrder(String completeOrder) {  
    this.completeOrder = completeOrder;  
}  

}

监听消息队列并处理类

package com.maple.security.web.async;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

@Component
public class QueueListener implements ApplicationListener {

private Logger logger = LoggerFactory.getLogger(QueueListener.class);

@Autowired  
private MockQueue mockQueue;

@Autowired  
private DeferredResultHolder deferredResultHolder;

@Override  
public void onApplicationEvent(ContextRefreshedEvent event) {

    new Thread(() -> {  
        while (true) {  
            if (StringUtils.isNotBlank(mockQueue.getCompleteOrder())) {  
                String orderNumber = mockQueue.getCompleteOrder();  
                logger.info("返回订单处理结果:" + orderNumber);  
                deferredResultHolder.getMap().get(orderNumber).setResult("place order success");

                mockQueue.setCompleteOrder(null);

            } else {  
                try {  
                    Thread.sleep(1000);  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }).start();

}  

}

异步处理结果类

/**
*
*/
package com.maple.security.web.async;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Component;
import org.springframework.web.context.request.async.DeferredResult;

/**
* @author hzc
*
*/
@Component
public class DeferredResultHolder {

private Map<String, DeferredResult<String>> map = new HashMap<String, DeferredResult<String>>();

public Map<String, DeferredResult<String>> getMap() {  
    return map;  
}

public void setMap(Map<String, DeferredResult<String>> map) {  
    this.map = map;  
}

}

3、异步处理配置