使用多线程提高REST服务器性能

Posted maple92

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用多线程提高REST服务器性能相关的知识,希望对你有一定的参考价值。

异步处理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<ContextRefreshedEvent> 

    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、异步处理配置

以上是关于使用多线程提高REST服务器性能的主要内容,如果未能解决你的问题,请参考以下文章

提高调用其他 API 的 Rest Webservice 性能的方法

jAVA基础 提高文件复制性能之多线程复制文件

jAVA基础 提高文件复制性能之多线程复制文件

1.linux服务器的性能分析与优化

在这种情况下,多线程如何帮助提高性能?

为啥这种令人尴尬的并行算法的性能没有随着多线程而提高?