我们正在使用Spring Boot来开发我们的服务。我们选择以异步方式执行此操作,并且遇到以下问题:我们在所有异步休息资源之上有以下方面:
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();
}
}
我们的应用程序中的嵌入式服务器正在进行中。问题出现了。似乎在经过将近一天之后,由于这方面的原因,CPU最终会飙升100%的红色。我调试了代码,从我的角度看似乎很好,但也许我错过了什么? 任何想法都会受到欢迎。谢谢, C.
答案 0 :(得分:1)
首先让我感到震惊的是你在代码中调用了两次joinPoint.proceed()。第一个是将它转换为DeferredResult,第二个是从方法返回时。你应该重写它,这样它只会被执行一次。您可以考虑将@Around注释用于执行&#39; (https://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-pointcuts-examples)而不是&#39;因为它允许您指定返回类型。在这种情况下,如果基于方法返回类型,您将不再需要它。
说完了,我不确定这是否能解决你的问题。我在那里缺乏背景,我不知道你想要达到的目标。可能有一种更简单的方法,因为在该上下文中使用延迟结果对我来说有点奇怪。此外,特别是导致100%资源使用的原因是什么?是否有一些线程无限运行或某些HTTP连接挂起?
答案 1 :(得分:0)
这个小重构怎么样?它是类型安全的,不需要反射,只需调用filename=""
while [[ $filename = "" ]];do
echo "Enter the file name"
read filename
if [[ -f $filename ]];then
echo "$filename exists"
else
echo "File name doesn't exists, so re-enter"
fi
done
一次。
此外,我认为在您的代码中proceed()
没有多大意义,我将其替换为ret.setErrorResult(ret)
,将实际的执行设置为错误结果。
我也希望你能原谅我重命名一些变数。它帮助我更好地了解发生了什么。我仍然不是百分百肯定,因为我对Spring一无所知(但很多关于AspectJ)。
setErrorResult(e)