解决函数短时间频繁调用性能瓶颈的思路建议

文章讲述了如何通过Java注解和切面编程在Web应用中实现接口请求的缓存策略,以减轻数据库压力,提高性能。具体使用了Spring框架和AspectJ进行静态方法拦截,并提供了示例代码展示缓存处理和更新机制。
摘要由CSDN通过智能技术生成
  在界面访问过程中,存在相同参数多个用户多次同时间段访问时,每次直接由业务逻辑生成返回数据,造成数据库等组件访问瓶颈。
  解决思路,是通过缓存组件,数据库或者文件系统对相同的参数访问,且无需精确的数据结果进行设定更新周期的缓冲。
  具体方法通过java注解,或者宏(c) 设置接口是否需要进行缓冲处理。然后在切面(宏)中加入相应的逻辑处理。下面以java为例子举例说明:
@Documented
@Retention(RUNTIME)
@Target({ ElementType.METHOD })
public @interface Staticable {

    //缓存时间 默认30分钟
    int timelapse() default 30;    
  //数据无效时,是否同步更新,还是延后更新 1:同步更新
    int freshSynchro() default 2;
}

切面代码:

package com.config.aspect;

import java.lang.reflect.Method;
import java.util.HashMap;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSONObject;
import com.common.CommonResult;
import com.common.ResultStatus;
import com.config.annotation.Staticable;
import com.config.aspect.thread.StaticThread;
import com.util.HttpCacheUtil;

/**
 * @Description: 页面静态化
 * @author liyw
 * @date 2020年10月29日 下午7:18:48
 *
 */
@Aspect
@Component
public class StaticableAspect{

	private static final Logger log = Logger.getLogger(StaticableAspect.class);
	@Resource
	private ThreadPoolTaskExecutor threadPoolTaskExecutor;

	/**
	 * @Description: 注解@Staticable拦截
	 */
	@Pointcut("@annotation(com.config.annotation.Staticable) " 
	      + "|| @within(com.config.annotation.Staticable)")
	protected void Staticable() {}

	@SuppressWarnings("unchecked")	
	@Around("Staticable()")
	@Order(10)

	public Object staticAround(ProceedingJoinPoint pjp) throws Throwable {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		// 从request信息中获取参数
		String url = request.getServletPath().toString();
		
		MethodSignature signature = (MethodSignature) pjp.getSignature();
	    Method method1 = signature.getMethod();
	    Integer timeLapse = 30;	
	    Integer freshSynchro = 2;
        //获取方法参数注解
	    Staticable staticable  = method1.getAnnotation(Staticable.class);
        timeLapse = staticable.timelapse();
	    buffByPage = staticable.buffByPage();
	    freshSynchro = staticable.freshSynchro();
	    if (freshSynchro == null || freshSynchro != 2) {
	    	freshSynchro = 1;
	    }
	    if (timeLapse == null) {
	    	timeLapse = 30;
	    }	    
	    Map<String, String[]> parameterMap = request.getParameterMap();	  
	 
	    JSONObject  var = (JSONObject)JSONObject.toJSON(parameterMap);	
	     
	    
	    //以访问串和参数json串的md5值作为缓存的key值
	    String keys = HttpCacheUtil.getKey(url, var.toJSONString());	   
	    
	    //取数据异常时,或符合取逻辑时执行实时取数据
	    try {
	    	//取缓存是否超时
	    	Boolean  isOverTime = HttpCacheUtil.overTime(keys);	
	    	//未超时, 或超时延时更新时, 取缓存数据返回
	    	if(!isOverTime || freshSynchro == 2){	    	   
	    		Object  rett =  HttpCacheUtil.getCache(keys);
	    		if(log.isDebugEnabled()) {
		    		log.debug("cache success : ->" + url);
		    	}
	    		if (isOverTime) {
	    			//超时且延期更新时,启动后续线程执行更新执行
		    		if(log.isDebugEnabled()) {
			    		log.debug("refresh success : ->" + url);
			    	}
			    	//线程后台完成更新数据
		    	    threadPoolTaskExecutor.execute(new StaticThread(pjp, keys, timeLapse));
	    		}
	    		return rett;
	    	}			
		}catch(Exception e) {
			
		}
	    Object  ret = pjp.proceed();
	    CommonResult<?> a = (CommonResult<?>) ret;
	    if ( a != null && ResultStatus.SUCCESS.getStatus() == a.getStatus()) {
	    	HttpCacheUtil.setCache(keys, a, timeLapse);
	    }
	      
		return ret;
	}
}

以上只完成从缓存进行缓存,没有实现数据库与文件缓存。

p

ackage com.config.aspect.thread;

import org.aspectj.lang.ProceedingJoinPoint;

import com.common.CommonResult;
import com.common.ResultStatus;
import com.zjhcsoft.util.HttpCacheUtil;

public class StaticThread implements Runnable{
	private ProceedingJoinPoint pjp = null;
	private String key = "";
	private Integer bufTimes = 30;
	
	public StaticThread(ProceedingJoinPoint pjp, String key, Integer bufTimes) {
		this.pjp = pjp;
		this.key = key;
		this.bufTimes = bufTimes;
	}
	public void run() {
		 try {
		    Object ret = pjp.proceed();			
		    CommonResult<?> a = (CommonResult<?>) ret;
		    if ( a != null && ResultStatus.SUCCESS.getStatus() == a.getStatus()) {
		       //执行成功,更新缓存
		    	HttpCacheUtil.setCache(key, a, bufTimes);
		    }
		 }catch(Exception e) {
			 e.printStackTrace();
		 } catch (Throwable e) {
			 e.printStackTrace();
		 }
	}
}
package com.util;

import com.common.CommonResult;
import com.exception.MngException;
import com.cache.CacheManagerFactory;
import com.cache.ICache;
import com.util.Md5Util;

/**
 * @Author: fanjiajie
 * @Date: 2020/12/7 11:08
 */
public class HttpCacheUtil {
	
	private static ICache cache = null;
	static {
		try {
		   //这里的CacheManagerFactory 可以用Redis来代替
			cache = CacheManagerFactory.getCache();
		} catch (Exception e) {			
		}
	}
	
	
	

	
	public static CommonResult<?> getCache(String key) throws Exception{		
		CommonResult<?> ret = (CommonResult<?>)cache.get(key);
		if (ret == null) {
			throw new MngException("暂无缓存操作");
		}			
	    return ret;
		
	}
	
	
	
	public static void setCache(String key,  CommonResult<?> value, Integer bufTimes)throws Exception{				
		Integer iMinutes = bufTimes;			
		cache.put(key, value);
		Long timeOverTime  = System.currentTimeMillis() + iMinutes * 60 * 1000;//分钟
		cache.put(key + "_time", timeOverTime);
		
	}
	
	public static String getKey(String function, String params) {
		 String key ="FN" + function + "_" + new Md5Util().getMD5ofStr(params);
		 return key;
	}
	
	public static Boolean overTime(String key) {
		try {
			Long  timeOverTime = (Long)cache.get(key + "_time");
			if (System.currentTimeMillis() > timeOverTime) {
				return true;
			}else {
				return false;
			}
		}catch(Exception e){			
		}
		return true;
	}
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值