sofastack / sofa-rpc

SOFARPC is a high-performance, high-extensibility, production-level Java RPC framework.
https://www.sofastack.tech/sofa-rpc/docs/Home
Apache License 2.0
3.83k stars 1.18k forks source link

sofa-rpc在依赖spring-boot-starter-web情况,异常栈不能正确的透传给调用端 #637

Closed iv587 closed 5 years ago

iv587 commented 5 years ago

sofa-rpc在依赖spring-boot-starter-web情况,通过http请求访问报类型转换失败

sofa-rpc的调用端是一个spring-boot-web 端 ,在一次调用中,当服务端出现异常后,不能正确的将异常栈返回给调用端

复现场景

启动服务端并发布服务,服务端提供一个测试的方法,该方法手动抛出异常。然后启动调用端,调用端在启动后立即在启动方法里进行一次远程调用,此时异常可以正确的返回给调用端。 通过发送http请求调用该方法,此时调用端则会抛出类型转换失败的异常

初步估计是因为servelet容器和spring的bean容器的上下文不一致导致的,还希望能给出官方建议和指导

Environment

leizhiyuan commented 5 years ago

@zonghaishang 帮忙看下。

chpengzh commented 5 years ago

问题定位如下:

  1. 直接使用idea 运行consumer代码,并执行curl -i http://localhost:8080/test触发RPC过程调用,consumer端会报附录日志;

  2. 在consumer模块下正确配置 spring-maven-plugin 并编译 runnable jar 执行就不会有图示问题。

  3. 去除runtime依赖spring-boot-devtools,idea环境下也能正常工作;

java.lang.ClassCastException: com.sofa.rpc.mydemo.rpc.RpcResult cannot be cast to com.sofa.rpc.mydemo.rpc.RpcResult
    at com.sofa.rpc.mydemo.rpc.TestServiceInf_proxy_0.testRpcRes(TestServiceInf_proxy_0.java)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.alipay.sofa.runtime.service.binding.JvmBindingAdapter$JvmServiceInvoker.doInvoke(JvmBindingAdapter.java:200)
    at com.alipay.sofa.runtime.spi.service.ServiceProxy.invoke(ServiceProxy.java:39)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.sun.proxy.$Proxy68.testRpcRes(Unknown Source)
    at com.sofa.rpc.mydemo.rpc.client.TestConsumer.testRpcRes(TestConsumer.java:15)
    at com.sofa.rpc.mydemo.rpc.client.TestController.testRpc(TestController.java:20)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:215)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:142)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:998)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:890)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:875)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
chpengzh commented 5 years ago

spring-boot-devtools的热部署功能,和rpc-sofa-boot-starterServiceProxy.invoke对上下文ClassLoader的设置逻辑有些冲突。

生产环境可能不会有这个问题。

iv587 commented 5 years ago

@chpengzh 好的,谢谢,暂时我先去掉spring-boot-devtools.