springboot接口慢_【SpringBoot】 一种解决接口返回慢的方式

前言

使用springboot开发后台代码的时候,很核心的一个功能是为前端提供接口,那么很可能你会遇到如下问题:

1. 接口里面调用的service层是第三方库或者第三方后台程序,导致访问很慢。

2. 接口需要轮询,或者参数较多的情况下导致返回慢。

本文旨在解决如上的接口返回慢的问题,并给出解决方案与思路。

一、使用Callable+FutureTask 实现多线程并发的方式

该思路是很容易想到的一种可行性方案,因为多线程可以大大提高后台处理速度,而且该方式是JAVA自带的。

思路:

1. 开N个线程

2. 引用callable 封装线程需要执行的task

3. 线程里面调用task,并执行。

4. 收集各线程的结果并返回

@Service

public class FutureTaskByReq {public static List> multiTaskGetReq(String projectid, String versionid) {

//开启多线程

ExecutorService exs = Executors.newFixedThreadPool(10);

List> retList = Collections.synchronizedList(new ArrayList());

try {

//结果集

// List list = new ArrayList();

List>> futureList = new ArrayList>>();

//启动线程池,10个任务固定线程数为5

for (int i = 0; i < version.length; i++) {

FutureTask> futureTask = new FutureTask>(new CallableTask(projectid, versionid));

//提交任务,添加返回,Runnable特性

exs.submit(futureTask);

//Future特性

futureList.add(futureTask);

}

//结果归集

while (futureList.size() > 0) {

Iterator>> iterable = futureList.iterator();

//遍历一遍

while (iterable.hasNext()) {

Future> future = iterable.next();

if (future.isDone() && !future.isCancelled()) {

//Future特性

retList.add(future.get());

//任务完成移除任务

iterable.remove();

} else {

//避免CPU高速轮循,可以休息一下。

Thread.sleep(1);

}

}

}

// System.out.println("list=" + retList);

// System.out.println("总耗时=" + (System.currentTimeMillis() - start) + ",取结果归集耗时=" + (System.currentTimeMillis() - getResultStart));

} catch (Exception e) {

e.printStackTrace();

} finally {

exs.shutdown();

}return retList;

}

/**

* @Description 回调方法

*/

public static class CallableTask implements Callable> {

String projectid;

String versionid;

public CallableTask(String projectid, String versionid) {

super();

this.projectid = projectid;

this.versionid = versionid;

}

@Override

public Map call() {

Map retmap=new HashMap<>();

//你想要执行的task

return retmap;

}

}

二、使用定时任务+缓存的方式解决接口返回慢的问题

思路与场景: 有些接口的访问量不大,或者请求的数据变动不频繁,可以暂时存放到缓存,例如redis里面。那么获取的时候就是即时获取。

springboot自带了 @EnableScheduling 注解,可以执行定时任务。采用cron 表达式即可精准定时执行。

Redis 则有大量的缓存策略与算法,这里推荐使用LRU算法进行存取都很方便。

定时部分:

@Component

@Configuration //1.主要用于标记配置类,兼备Component的效果。

@EnableScheduling // 2.开启定时任务

public class LocalSchedule {

//添加定时任务,每天12点定时执行

@Scheduled(cron = "0 0 12 * * ?" )

//或直接指定时间间隔,例如:5秒

//@Scheduled(fixedRate=5000)

private void configureTasks() {

//TODO 需要执行的定时任务,主要是比较慢的接口

System.err.println("执行静态1定时任务时间: " + LocalDateTime.now());

}

}

LRU算法:

/**

* 使用LRU策略进行一些数据缓存。

*/

public class LRULocalCache {

/**

* 默认有效时长,单位:秒

*/

private static final long DEFUALT_TIMEOUT = ;private static final Map map;

private static final Timer timer;

/**

* 初始化

*/

static {

timer = new Timer();

// map = new LRUMap<>();

map = new ConcurrentHashMap<>();

}

/**

* 私有构造函数,工具类不允许实例化

*/

private LRULocalCache() {

}

/**

* 基于LRU策略的map

*

* @param

* @param

*/

static class LRUMap extends LinkedHashMap {

/**

* 读写锁

*/

private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

private final Lock rLock = readWriteLock.readLock();

private final Lock wLock = readWriteLock.writeLock();

/**

* 默认缓存容量

*/

private static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;

/**

* 默认最大缓存容量

*/

// private static final int DEFAULT_MAX_CAPACITY = 1 << 30;

private static final int DEFAULT_MAX_CAPACITY = 1 << 18;

/**

* 加载因子

*/

private static final float DEFAULT_LOAD_FACTOR = 0.75f;

public LRUMap() {

super(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);

}

public LRUMap(int initialCapacity) {

super(initialCapacity, DEFAULT_LOAD_FACTOR);

}

public void clear() {

wLock.lock();

try {

super.clear();

} finally {

wLock.unlock();

}

}

/**

* 重写LinkedHashMap中removeEldestEntry方法;

* 新增元素的时候,会判断当前map大小是否超过DEFAULT_MAX_CAPACITY,超过则移除map中最老的节点;

*

* @param eldest

* @return

*/

protected boolean removeEldestEntry(Map.Entry eldest) {

return size() > DEFAULT_MAX_CAPACITY;

}

}

/**

* 清除缓存任务类

*/

static class CleanWorkerTask extends TimerTask {

private String key;

public CleanWorkerTask(String key) {

this.key = key;

}

public void run() {

map.remove(key);

}

}

/**

* 增加缓存

*

* @param key

* @param value

*/

public static void add(String key, Object value) {

map.put(key, value);

timer.schedule(new CleanWorkerTask(key), DEFUALT_TIMEOUT);

}

/**

* 增加缓存

*

* @param key

* @param value

* @param timeout 有效时长

*/

public static void put(String key, Object value, int timeout) {

map.put(key, value);

timer.schedule(new CleanWorkerTask(key), timeout * SECOND_TIME);

}

/**

* 增加缓存

*

* @param key

* @param value

* @param expireTime 过期时间

*/

public static void put(String key, Object value, Date expireTime) {

map.put(key, value);

timer.schedule(new CleanWorkerTask(key), expireTime);

}

/**

* 获取缓存

*

* @param key

* @return

*/

public static Object get(String key) {

return map.get(key);

}

}

标签:返回,SpringBoot,接口,static,param,key,new,public,String

来源: https://www.cnblogs.com/Ronaldo-HD/p/11510681.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值