javascript
springboot接口慢_【SpringBoot】 一种解决接口返回慢的方式
前言
使用springboot開發后臺代碼的時候,很核心的一個功能是為前端提供接口,那么很可能你會遇到如下問題:
1. 接口里面調用的service層是第三方庫或者第三方后臺程序,導致訪問很慢。
2. 接口需要輪詢,或者參數較多的情況下導致返回慢。
本文旨在解決如上的接口返回慢的問題,并給出解決方案與思路。
一、使用Callable+FutureTask 實現多線程并發的方式
該思路是很容易想到的一種可行性方案,因為多線程可以大大提高后臺處理速度,而且該方式是JAVA自帶的。
1. 開N個線程
2. 引用callable 封裝線程需要執行的task
3. 線程里面調用task,并執行。
4. 收集各線程的結果并返回
@ServicepublicclassFutureTaskByReq{publicstaticList>multiTaskGetReq(Stringprojectid,Stringversionid){//開啟多線程ExecutorServiceexs=Executors.newFixedThreadPool(10);List>retList=Collections.synchronizedList(newArrayList());try{//結果集// List list = new ArrayList();List>>futureList=newArrayList>>();//啟動線程池,10個任務固定線程數為5for(inti=0;i>futureTask=newFutureTask>(newCallableTask(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(Exceptione){e.printStackTrace();}finally{exs.shutdown();}returnretList;}/** * @Description 回調方法 */publicstaticclassCallableTaskimplementsCallable>{Stringprojectid;Stringversionid;publicCallableTask(Stringprojectid,Stringversionid){super();this.projectid=projectid;this.versionid=versionid;}@OverridepublicMapcall(){Mapretmap=newHashMap<>();//你想要執行的taskreturnretmap;}}
二、使用定時任務+緩存的方式解決接口返回慢的問題
思路與場景: 有些接口的訪問量不大,或者請求的數據變動不頻繁,可以暫時存放到緩存,例如redis里面。那么獲取的時候就是即時獲取。
springboot自帶了?@EnableScheduling 注解,可以執行定時任務。采用cron 表達式即可精準定時執行。
Redis 則有大量的緩存策略與算法,這里推薦使用LRU算法進行存取都很方便。
定時部分:
@Component@Configuration//1.主要用于標記配置類,兼備Component的效果。@EnableScheduling// 2.開啟定時任務publicclassLocalSchedule{//添加定時任務,每天12點定時執行@Scheduled(cron="0 0 12 * * ?")//或直接指定時間間隔,例如:5秒//@Scheduled(fixedRate=5000)privatevoidconfigureTasks(){//TODO 需要執行的定時任務,主要是比較慢的接口System.err.println("執行靜態1定時任務時間: "+LocalDateTime.now());}}
LRU算法:
/** * 使用LRU策略進行一些數據緩存。 */publicclassLRULocalCache{/** * 默認有效時長,單位:秒 */privatestaticfinallongDEFUALT_TIMEOUT=;privatestaticfinalMapmap;privatestaticfinalTimertimer;/** * 初始化 */static{timer=newTimer();// map = new LRUMap<>();map=newConcurrentHashMap<>();}/** * 私有構造函數,工具類不允許實例化 */privateLRULocalCache(){}/** * 基于LRU策略的map * * @param * @param */staticclassLRUMapextendsLinkedHashMap{/** * 讀寫鎖 */privatefinalReadWriteLockreadWriteLock=newReentrantReadWriteLock();privatefinalLockrLock=readWriteLock.readLock();privatefinalLockwLock=readWriteLock.writeLock();/** * 默認緩存容量 */privatestaticfinalintDEFAULT_INITIAL_CAPACITY=1<<4;/** * 默認最大緩存容量 */// private static final int DEFAULT_MAX_CAPACITY = 1 << 30;privatestaticfinalintDEFAULT_MAX_CAPACITY=1<<18;/** * 加載因子 */privatestaticfinalfloatDEFAULT_LOAD_FACTOR=0.75f;publicLRUMap(){super(DEFAULT_INITIAL_CAPACITY,DEFAULT_LOAD_FACTOR);}publicLRUMap(intinitialCapacity){super(initialCapacity,DEFAULT_LOAD_FACTOR);}publicvoidclear(){wLock.lock();try{super.clear();}finally{wLock.unlock();}}/** * 重寫LinkedHashMap中removeEldestEntry方法; * 新增元素的時候,會判斷當前map大小是否超過DEFAULT_MAX_CAPACITY,超過則移除map中最老的節點; * * @param eldest * @return */protectedbooleanremoveEldestEntry(Map.Entryeldest){returnsize()>DEFAULT_MAX_CAPACITY;}}/** * 清除緩存任務類 */staticclassCleanWorkerTaskextendsTimerTask{privateStringkey;publicCleanWorkerTask(Stringkey){this.key=key;}publicvoidrun(){map.remove(key);}}/** * 增加緩存 * * @param key * @param value */publicstaticvoidadd(Stringkey,Objectvalue){map.put(key,value);timer.schedule(newCleanWorkerTask(key),DEFUALT_TIMEOUT);}/** * 增加緩存 * * @param key * @param value * @param timeout 有效時長 */publicstaticvoidput(Stringkey,Objectvalue,inttimeout){map.put(key,value);timer.schedule(newCleanWorkerTask(key),timeout*SECOND_TIME);}/** * 增加緩存 * * @param key * @param value * @param expireTime 過期時間 */publicstaticvoidput(Stringkey,Objectvalue,DateexpireTime){map.put(key,value);timer.schedule(newCleanWorkerTask(key),expireTime);}/** * 獲取緩存 * * @param key * @return */publicstaticObjectget(Stringkey){returnmap.get(key);}}
來源:博客園
作者:Charles-MQ
鏈接:https://www.cnblogs.com/Ronaldo-HD/p/11510681.html
總結
以上是生活随笔為你收集整理的springboot接口慢_【SpringBoot】 一种解决接口返回慢的方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 里面有面和点_鲜虾韭菜水晶饺,皮薄馅大,
- 下一篇: 启动指定参数_SpringBoot的三种