前言
因近期接到一个需求,需要对平台用户的行为进行记录,最常见的做法就是使用AOP,然后日志直接入库。这种做法在并发量不高的系统上是可行的,但当系统流量负载比较高时,日志直接入库势必会对系统性能造成一定的影响。因此今天将分享使用阻塞队列来实现一个简单的MQ来定时批量处理高并发下的海量日志。
什么是BlockingQueue?
阻塞队列(BlockingQueue)是区别于普通队列多了两个附加操作的线程安全的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。
下面将介绍具体的实现步骤
1.创建一个系统日志切面类
拦截接口请求,封装日志信息,放到队列中去
/**
* 系统日志切面处理类
*/
@Aspect
@Component
public class WebLogAspect {
private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
ThreadLocal<SystemLogEntity> systemLogThreadLocal = new ThreadLocal<>();
/**
* 1.定义一个切入点,可以是一个规则表达式,比如下例中某个package下的所有函数,也可以是一个注解
*
*/
@Pointcut("@within(org.springframework.web.bind.annotation.RestController) || @within(org.springframework.stereotype.Controller)")
public void webLogCut() {
}
/**
* 前置通知, 在方法执行之前执行
*
* @param joinPoint
* @throws Throwable
*/
@Before("webLogCut()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
logger.info("URL: {}", request.getRequestURL().toString());
StringBuffer url = request.getRequestURL();
String requestDomain = url.delete(url.length() - request.getRequestURI().length(), url.length()).append("/").toString();
logger.info("DOMAIN: {}", requestDomain);
logger.info("IP: {}", IPAddressUtil.getClientIpAddress(request));
logger.info("HTTP_METHOD: {}", request.getMethod());
logger.info("CLASS_METHOD: {}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
logger.info("ARGS_ARRAY: {}", joinPoint.getArgs());
StringBuilder params = new StringBuilder();
Enumeration<String> enums = request.getParameterNames();
while (enums.hasMoreElements()) {
String name = enums.nextElement();
String value = request.getParameter(name);
params.append(name).append("=").append(request.getParameter</