Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Spring MVC asynchronous requests, fix #2716. #2781

Closed
wants to merge 5 commits into from
Closed

Support Spring MVC asynchronous requests, fix #2716. #2781

wants to merge 5 commits into from

Conversation

howiekang
Copy link
Contributor

@howiekang howiekang commented Jul 8, 2022

Describe what this PR does / why we need it

支持Spring MVC的异步请求

Does this pull request fix one issue?

(#2716)

Describe how you did it

1 更改了 AbstractSentinelInterceptor 的继承接口为 AsyncHandlerInterceptor 将限流的逻辑移动到了afterConcurrentHandlingStarted 中实现。

异步请求的拦截逻辑 request -> afterConcurrentHandlingStarted -> preHandle -> afterCompletion -> resopnse
其中preHandle 做了方法返回值判断,如果是异步方法就不会执行了。

同步请求的拦截逻辑 request -> preHandle -> afterConcurrentHandlingStarted -> afterCompletion -> resopnse

支持的异步返回值,与Spring的 handleReturnValue 中的一致,WebAsyncTask、Callable、DeferredResult、ListenableFuture、CompletionStage

Describe how to verify it

test case

Special notes for reviews

@sczyh30

@sczyh30 sczyh30 added kind/enhancement Category issues or prs related to enhancement. to-review To review area/integrations Issues or PRs related to integrations with open-source components labels Jul 9, 2022
@@ -15,28 +15,29 @@
*/
package com.alibaba.csp.sentinel.adapter.spring.webmvc;

import javax.servlet.http.HttpServletRequest;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove the unnecessary changes.

/**
* Since request may be reprocessed in flow if any forwarding or including or other action
* happened (see {@link javax.servlet.ServletRequest#getDispatcherType()}) we will only
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove the unnecessary changes.

@@ -48,11 +49,11 @@
* return mav;
* }
* </pre>
*
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove the unnecessary changes.

@@ -64,54 +65,76 @@ public AbstractSentinelInterceptor(BaseWebMvcConfig config) {
AssertUtil.assertNotBlank(config.getRequestAttributeName(), "requestAttributeName should not be blank");
this.baseWebMvcConfig = config;
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove the unnecessary changes.

/**
* @param request
* @param rcKey
* @param step
* @return reference count after increasing (initial value as zero to be increased)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove the unnecessary changes.

}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove the unnecessary changes.

@@ -139,15 +162,15 @@ public void afterCompletion(HttpServletRequest request, HttpServletResponse resp
if (increaseReferece(request, this.baseWebMvcConfig.getRequestRefName(), -1) != 0) {
return;
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove the unnecessary changes.

Entry entry = getEntryInRequest(request, baseWebMvcConfig.getRequestAttributeName());
if (entry == null) {
// should not happen
RecordLog.warn("[{}] No entry found in request, key: {}",
getClass().getSimpleName(), baseWebMvcConfig.getRequestAttributeName());
return;
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove the unnecessary changes.

} catch (BlockException e) {
try {
handleBlockException(request, response, e);
} finally {
ContextUtil.exit();
}
return false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the return false logic missed.


HandlerMethod handlerMethod = (HandlerMethod) handler;
Class<?> returnType = handlerMethod.getReturnType().getParameterType();
return WebAsyncTask.class.isAssignableFrom(returnType) ||
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give some case about the return type is void?

@howiekang
Copy link
Contributor Author

howiekang commented Jul 18, 2022

我刚开始以为这个问题是异步请求 preHandle 执行两次造成了,之前的PR也是针对这个问题修复的。现在我发现并不是preHandle的问题,而是因为这个提交 #1681 他在请求属性上附加了一个计数器。只要计数器平衡(预期结果相符)的时候才执行SphU.entryEntry.exit

对于异步请求,preHandle 会执行两次。所以 afterCompletion 中关于Entry.exit的逻辑不会再执行了。我测试之后发现,只要能够限制preHandle 的执行,不管什么时候都要保证Entry.exit的顺利执行,所以我保留了preHandle 中的计数器,用来过滤重复的执行,去掉了afterCompletion 对于Entry.exit的限制。只要Entry存在都必须正常执行退出逻辑。

@brotherlu-xcq
Copy link
Collaborator

Ok,可以把评论里面的那些缩进问题修复一下吗?

Copy link
Collaborator

@brotherlu-xcq brotherlu-xcq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

麻烦把缩进问题处理一下。

@brotherlu-xcq brotherlu-xcq changed the title Support Spring MVC asynchronous requests,fix https://github.com/aliba… Support Spring MVC asynchronous requests, fix #2716. Jul 22, 2022
@@ -136,18 +136,14 @@ protected String getContextName(HttpServletRequest request) {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
if (increaseReferece(request, this.baseWebMvcConfig.getRequestRefName(), -1) != 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe don't remove this, but add the code to preHandle is better.

increaseReferece(request, this.baseWebMvcConfig.getRequestRefName(), -1)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个PR太乱了,我重新提交了一个 #2795

# Conflicts:
#	sentinel-adapter/sentinel-spring-webmvc-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webmvc/AbstractSentinelInterceptor.java
@sczyh30 sczyh30 removed the to-review To review label Nov 8, 2022
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/integrations Issues or PRs related to integrations with open-source components kind/enhancement Category issues or prs related to enhancement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants