/* * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the dreamlu.net developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: Chill 庄骞 (smallchill@163.com) */ package org.springblade.core.boot.config; import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springblade.core.boot.error.ErrorType; import org.springblade.core.boot.error.ErrorUtil; import org.springblade.core.context.BladeContext; import org.springblade.core.context.BladeRunnableWrapper; import org.springblade.core.launch.props.BladeProperties; import org.springblade.core.log.constant.EventConstant; import org.springblade.core.log.event.ErrorLogEvent; import org.springblade.core.log.model.LogError; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.boot.task.TaskExecutorCustomizer; import org.springframework.boot.task.TaskSchedulerCustomizer; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.lang.NonNull; import org.springframework.scheduling.annotation.AsyncConfigurerSupport; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.util.ErrorHandler; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ThreadPoolExecutor; /** * 异步处理 * * @author Chill */ @Slf4j @Configuration @EnableAsync @EnableScheduling @AllArgsConstructor public class BladeExecutorConfiguration extends AsyncConfigurerSupport { private final BladeContext bladeContext; private final BladeProperties bladeProperties; private final ApplicationEventPublisher publisher; @Bean public TaskExecutorCustomizer taskExecutorCustomizer() { return taskExecutor -> { taskExecutor.setThreadNamePrefix("async-task-"); taskExecutor.setTaskDecorator(BladeRunnableWrapper::new); taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); }; } @Bean public TaskSchedulerCustomizer taskSchedulerCustomizer() { return taskExecutor -> { taskExecutor.setThreadNamePrefix("async-scheduler"); taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); taskExecutor.setErrorHandler(new BladeErrorHandler(bladeContext, bladeProperties, publisher)); }; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return new BladeAsyncUncaughtExceptionHandler(bladeContext, bladeProperties, publisher); } @RequiredArgsConstructor private static class BladeAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler { private final BladeContext bladeContext; private final BladeProperties bladeProperties; private final ApplicationEventPublisher eventPublisher; @Override public void handleUncaughtException(@NonNull Throwable error, @NonNull Method method, @NonNull Object... params) { log.error("Unexpected exception occurred invoking async method: {}", method, error); LogError logError = new LogError(); // 服务信息、环境、异常类型 logError.setParams(ErrorType.ASYNC.getType()); logError.setEnv(bladeProperties.getEnv()); logError.setServiceId(bladeProperties.getName()); logError.setRequestUri(bladeContext.getRequestId()); // 堆栈信息 ErrorUtil.initErrorInfo(error, logError); Map event = new HashMap<>(16); event.put(EventConstant.EVENT_LOG, logError); eventPublisher.publishEvent(new ErrorLogEvent(event)); } } @RequiredArgsConstructor private static class BladeErrorHandler implements ErrorHandler { private final BladeContext bladeContext; private final BladeProperties bladeProperties; private final ApplicationEventPublisher eventPublisher; @Override public void handleError(@NonNull Throwable error) { log.error("Unexpected scheduler exception", error); LogError logError = new LogError(); // 服务信息、环境、异常类型 logError.setParams(ErrorType.SCHEDULER.getType()); logError.setServiceId(bladeProperties.getName()); logError.setEnv(bladeProperties.getEnv()); logError.setRequestUri(bladeContext.getRequestId()); // 堆栈信息 ErrorUtil.initErrorInfo(error, logError); Map event = new HashMap<>(16); event.put(EventConstant.EVENT_LOG, logError); eventPublisher.publishEvent(new ErrorLogEvent(event)); } } }