Browse Source

v1.0.0-fix: 进行dubbo异常机制的处理

sckw-developer 2 tháng trước cách đây
mục cha
commit
c0b6a430e7

+ 85 - 0
sckw-common/sckw-common-remote/src/main/java/com/sckw/remote/filter/DubboConsumerExceptionFilter.java

@@ -0,0 +1,85 @@
+package com.sckw.remote.filter;
+
+import org.apache.dubbo.common.constants.CommonConstants;
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.*;
+import org.apache.dubbo.rpc.service.GenericService;
+
+import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_FILTER_VALIDATION_EXCEPTION;
+
+@Activate(group = CommonConstants.CONSUMER)
+public class DubboConsumerExceptionFilter implements Filter, Filter.Listener {
+    private ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(DubboConsumerExceptionFilter.class);
+
+    @Override
+    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
+        return invoker.invoke(invocation);
+    }
+
+    @Override
+    public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
+        if (appResponse.hasException() && GenericService.class != invoker.getInterface()) {
+            try {
+                Throwable exception = appResponse.getException();
+                
+                // 直接抛出RuntimeException,避免将底层异常信息暴露给调用方
+                String className = exception.getClass().getName();
+                if (className.startsWith("java.") || className.startsWith("javax.")) {
+                    return;
+                }
+                
+                // 自定义异常处理
+                if (className.startsWith("com.sckw.core.exception")) {
+                    return;
+                }
+                
+                // Dubbo异常处理
+                if (exception instanceof RpcException) {
+                    // 记录RpcException日志,但不暴露给前端
+                    logger.error(CONFIG_FILTER_VALIDATION_EXCEPTION, "", "", 
+                        "Dubbo RpcException. service: " + invoker.getInterface().getName() + 
+                        ", method: " + invocation.getMethodName() + 
+                        ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), 
+                        exception);
+                    
+                    // 包装为通用异常信息返回给客户端
+                    appResponse.setException(new RuntimeException("服务暂时不可用,请稍后重试"));
+                    return;
+                }
+
+                // 记录异常日志
+                logger.error(CONFIG_FILTER_VALIDATION_EXCEPTION, "", "", 
+                    "Dubbo consumer caught exception. service: " + invoker.getInterface().getName() + 
+                    ", method: " + invocation.getMethodName() + 
+                    ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), 
+                    exception);
+
+                // 包装为RuntimeException并返回给客户端
+                appResponse.setException(new RuntimeException("服务调用异常,请稍后重试"));
+            } catch (Throwable e) {
+                logger.warn(CONFIG_FILTER_VALIDATION_EXCEPTION, "", "", 
+                    "Fail to ExceptionFilter when called by " + RpcContext.getServiceContext().getRemoteHost() + 
+                    ". service: " + invoker.getInterface().getName() + 
+                    ", method: " + invocation.getMethodName() + 
+                    ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
+            }
+        }
+    }
+
+    @Override
+    public void onError(Throwable e, Invoker<?> invoker, Invocation invocation) {
+        logger.error(CONFIG_FILTER_VALIDATION_EXCEPTION, "", "", 
+            "Got unchecked and undeclared exception which called by " + RpcContext.getServiceContext().getRemoteHost() + 
+            ". service: " + invoker.getInterface().getName() + 
+            ", method: " + invocation.getMethodName() + 
+            ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
+    }
+
+    // For test purpose
+    public void setLogger(ErrorTypeAwareLogger logger) {
+        this.logger = logger;
+    }
+}