apache / shenyu

Apache ShenYu is a Java native API Gateway for service proxy, protocol conversion and API governance.
https://shenyu.apache.org/
Apache License 2.0
8.45k stars 2.94k forks source link

[Question] No thread-bound request found: Are you referring to request attributes outside of an actual web request #4667

Closed HeiXXwowoTou closed 1 year ago

HeiXXwowoTou commented 1 year ago

Question

environment: shenyu: 2.5.1, spring-boot: 2.3.2.RELEASE, spring-cloud: Hoxton.SR9 spring-cloud-alibaba: 2.2.6.RELEASE spring-cloud-starter-dubbo: 2.2.6.RELEASE jdk:11

my own service dependent and config:

<dependency>
        <groupId>org.apache.shenyu</groupId>
        <artifactId>shenyu-spring-boot-starter-client-apache-dubbo</artifactId>
        <version>2.5.1</version>
</dependency>
server:
  port: 9990
spring:
  profiles:
    active: dev
  application:
    name: business-center-finance-server
  cloud:
    nacos:
      config:
        server-addr: ${nacos.address}
        namespace: ${nacos.config-namespace}
        file-extension: yaml
#        shared-configs:
#          - data-id: dubbo.yaml
#            group: public
#            refresh: true
      discovery:
        server-addr: ${nacos.address}
        namespace: ${nacos.discovery-namespace}
#        group: ${nacos.discovery-namespace}
shenyu:
  register:
    registerType: nacos #zookeeper #etcd #nacos #consul
    serverLists: localhost:8848 #http://localhost:9095 #localhost:2181 #http://localhost:2379 #localhost:8848
    props:
      username: nacos
      password: 4PBZ8fjEnZDhQY
      nacosNameSpace: dev
  client:
    dubbo:
      props:
        contextPath: /finance
        appName: ${spring.application.name}
dubbo:
  application:
    name: ${spring.application.name}
  registry:
    address: nacos://localhost:8848
    namespace: dev
  protocol:
    name: dubbo
    port: 20887
  scan:
    base-packages: com.labway.business.center.finance.service.impl

My problem is as follows: After I used my dubbo to access our shenyu gateway, the GET request could be successful, but my Post interface, using the body parameter, my program has an error

java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at com.labway.sso.starter.common.SsoUserHelper.getLoginUser(SsoUserHelper.java:23) ~[labway-sso-token-starter-1.1.1-SNAPSHOT.jar:na]
    at com.labway.business.center.core.user.LoginUserInfoUtil.getUserHasOrgs(LoginUserInfoUtil.java:39) ~[classes/:na]
    at com.labway.business.center.finance.aop.DataPermissionPointcut.invokeDataPermissionPointcut(DataPermissionPointcut.java:77) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at com.labway.business.center.finance.service.impl.CarNoServiceImpl$$EnhancerBySpringCGLIB$$c73ce277.setUpDefaultCarNoAble(<generated>) ~[classes/:na]
    at com.labway.business.center.finance.service.impl.CarNoServiceImpl$$FastClassBySpringCGLIB$$f5f13257.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    at com.labway.business.center.finance.service.impl.CarNoServiceImpl$$EnhancerBySpringCGLIB$$56f1f1fe.setUpDefaultCarNoAble(<generated>) ~[classes/:na]
    at org.apache.dubbo.common.bytecode.Wrapper8.invokeMethod(Wrapper8.java) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:47) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:84) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker.invoke(DelegateProviderMetaDataInvoker.java:56) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:56) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:52) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:89) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:46) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:77) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:129) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:147) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:41) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:83) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:145) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:100) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:175) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:51) ~[dubbo-2.7.8.jar:2.7.8]
    at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57) ~[dubbo-2.7.8.jar:2.7.8]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
    at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

I suspect it may be because the body request body or the request header has not been passed, but I have not found relevant information for the configuration or operation of this part, so I ask for help

HeiXXwowoTou commented 1 year ago

I discussed with my team leader just now, which might be because of the following code. Is there any good way

package com.labway.sso.starter.common;

import com.labway.sso.core.user.SsoUser;
import java.util.Objects;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

public class SsoUserHelper {
    private SsoUserHelper() {
    }

    public static SsoUser getLoginUser() {
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
        Object userObject = request.getAttribute("labway_sso_user");
        return Objects.isNull(userObject) ? null : (SsoUser)userObject;
    }
}
yu199195 commented 1 year ago

whats the code from ?

HeiXXwowoTou commented 1 year ago

whats the code from ?

This code is a project of my own

HeiXXwowoTou commented 1 year ago

whats the code from ?

In case I wasn't clear enough, this code is a class that gets user information from our login, and my dubbo project depends on our login

HeiXXwowoTou commented 1 year ago

I discussed with my team leader just now, which might be because of the following code. Is there any good way

package com.labway.sso.starter.common;

import com.labway.sso.core.user.SsoUser;
import java.util.Objects;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

public class SsoUserHelper {
    private SsoUserHelper() {
    }

    public static SsoUser getLoginUser() {
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
        Object userObject = request.getAttribute("labway_sso_user");
        return Objects.isNull(userObject) ? null : (SsoUser)userObject;
    }
}

我觉得问题可能是我的这个类去获取request对象中的信息,这个request已经被读取过的这种问题?类似于 主线程读取过之后子线程就无法读取这样?这个问题可以提供一个解决思路吗

HeiXXwowoTou commented 1 year ago

目前我的解决方案,在网关层定义了过滤器,将token信息传递在RpcContext中,在我的服务中进行获取