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

service层获取requst上下文时,优先从restStrategyContext获取,在没使用异步情况下,会不会有内存泄漏问题 #200

Open
testc1 opened this issue Feb 21, 2023 · 5 comments

Comments

@testc1
Copy link

testc1 commented Feb 21, 2023

每次getCurret时,都给当前线程绑定了一个初始的context,但是并没有看见调用clean方法

public ServletRequestAttributes getRestAttributes() {
// 异步场景下 会复制请求信息到RestStrategyContext
RequestAttributes requestAttributes = RestStrategyContext.getCurrentContext().getRequestAttributes();
if (requestAttributes == null) {
requestAttributes = RequestContextHolder.getRequestAttributes();
}
return (ServletRequestAttributes) requestAttributes;
}

@testc1
Copy link
Author

testc1 commented Feb 21, 2023

还有一个问题,在使用了Agent插件时,已经设置在了request中,为什么还在再设置在restStrategyContext中,但道理两个都设置了,但是异步场景下,直接从RequestContextHolder.getRequestAttributes();中还是娶不到,只有从RestStrategyContext.getCurrentContext().getRequestAttributes();才能取到
@OverRide
public Object create() {
RequestAttributes request = RequestContextHolder.getRequestAttributes();
if (requestDecoratorEnabled) {
if (null != request) {
request = ServiceStrategyRequestDecoratorFactory.decorateRequestAttributes(request);
}
}
return request;
}

@SuppressWarnings("unchecked")
@Override
public void before(Object object) {
    if (object instanceof RequestAttributes) {
        RequestAttributes requestAttributes = (RequestAttributes) object;
        RequestContextHolder.setRequestAttributes(requestAttributes);
        RestStrategyContext.getCurrentContext().setRequestAttributes(requestAttributes);
    }
}

@HaojunRen
Copy link
Member

第一个问题,如果用了同步,上下文会从RequestContextHolder去取,这是Spring Boot自带的,它会主动清理,如果用了异步,那必须用DiscoveryAgent,它里面有清理代码,所有,两种情况都不会造成泄露

第二个问题,Agent下,Spring Boot 自带的会发生取不到的情况,所以框架自己维护了一个threadlocal,保证能取到

@testc1
Copy link
Author

testc1 commented Feb 21, 2023

①RequestAttributes requestAttributes = RestStrategyContext.getCurrentContext().getRequestAttributes();
②public static RestStrategyContext getCurrentContext() {
return THREAD_LOCAL.get();
}

public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}

在调入到第三部的时候,会调用 private static final ThreadLocal THREAD_LOCAL = new ThreadLocal() {
@OverRide
protected RestStrategyContext initialValue() {
return new RestStrategyContext();
}
};初始化方法,给每个线程绑定了一个RestStrategyContext,同步的时候没有地方清除这个绑定,这样会有问题吗?

@testc1
Copy link
Author

testc1 commented Feb 21, 2023

public ServletRequestAttributes getRestAttributes() {
RequestAttributes requestAttributes = RestStrategyContext.getCurrentContext().getRequestAttributes();
if (requestAttributes == null) {
requestAttributes = RequestContextHolder.getRequestAttributes();
}

    return (ServletRequestAttributes) requestAttributes;
}

这里获取的时候,可以换成先从 RequestContextHolder.getRequestAttributes() 这里为空,再从RestStrategyContext.getCurrentContext().getRequestAttributes()里边取吗?这样有问题吗?能不能避免先从RestStrategyContext中取,同步调用下,给当前线程绑定RestStrategyContext而没清理的情况

@HaojunRen
Copy link
Member

同步情况下,RestStrategyContext.getCurrentContext().getRequestAttributes()返回的是null

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants