Nous utilisons Spring Boot pour développer nos services. Nous avons choisi de le faire d'une manière async et nous sommes confrontés au problème suivant: Nous avons l'aspect suivant au-dessus de toutes nos ressources de repos async:Spring Boot DeferredResult L'aspect rend le CPU très haut
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.context.request.async.DeferredResult;
@Aspect
@Component
public class TerminatedUsersAspect {
private static final Logger LOGGER = LoggerFactory.getLogger("[TERMINATED_USERS]");
public static final ThreadLocal<String> ID_LOCAL = new ThreadLocal<>();
@Autowired
private UserRepository userRepo;
@Autowired
private UserService userService;
@Autowired
private ExecutorService executorService;
@SuppressWarnings("unchecked")
@Around("within(com.test..*) && @annotation(authorization)")
public Object checkForId(ProceedingJoinPoint joinPoint, Authorization authorization) throws Throwable {
final MethodInvocationProceedingJoinPoint mJoinPoint = (MethodInvocationProceedingJoinPoint) joinPoint;
final MethodSignature signature = (MethodSignature) mJoinPoint.getSignature();
final DeferredResult<Object> ret = new DeferredResult<>(60000L);
final String id = ID_LOCAL.get();
if (signature.getReturnType().isAssignableFrom(DeferredResult.class) && (id != null)) {
userRepo.getAccountStatus(id).thenAcceptAsync(status -> {
boolean accountValid = userService.isAccountValid(status, true);
if (!accountValid) {
LOGGER.debug("AccountId: {} is not valid. Rejecting with 403", id);
ret.setErrorResult(new ResponseEntity<String>("Invalid account.", HttpStatus.FORBIDDEN));
return;
}
try {
final DeferredResult<Object> funcRet = (DeferredResult<Object>) joinPoint.proceed();
funcRet.setResultHandler(r -> {
ret.setResult(r);
});
funcRet.onTimeout(() -> {
ret.setResult(new AsyncRequestTimeoutException());
});
} catch (Throwable e) {
ret.setErrorResult(ret);
}
}, executorService).exceptionally(ex -> {
ret.setErrorResult(ex);
return null;
});
return ret;
}
return joinPoint.proceed();
}
}
Notre serveur embarqué dans l'application est undertow. Le problème se pose à temps. Il semble que, après presque un jour à cause de cet aspect, les processeurs finissent par atteindre 100% de rouge. J'ai débogué le code et semble aller bien de mon point de vue, mais peut-être qu'il me manque quelque chose? Toutes les idées seraient les bienvenues. Merci, C.
Je suis d'accord avec tout ce qui est dit ici. Vous semblez appliquer l'aspect trop largement, le grand «si» et toutes les choses coûteuses de réflexion ne sont pas nécessaires. Alors le 'procéder()' après le 'si 'ne serait pas nécessaire en premier lieu, mais si vous l'utilisez, mettez-le au moins dans une branche' else'. Je vais préparer un petit échantillon pour vous. – kriegaex