日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

dubbo异常处理

發(fā)布時間:2024/7/5 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 dubbo异常处理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

dubbo異常處理

我們的項目使用了dubbo進行不同系統(tǒng)之間的調(diào)用。
每個項目都有一個全局的異常處理,對于業(yè)務異常,我們會拋出自定義的業(yè)務異常(繼承RuntimeException)。
全局的異常處理會根據(jù)不同的異常類型進行不同的處理。
最近我們發(fā)現(xiàn),某個系統(tǒng)調(diào)用dubbo請求,provider端(服務提供方)拋出了自定義的業(yè)務異常,但consumer端(服務消費方)拿到的并不是自定義的業(yè)務異常。

這是為什么呢?還需要從dubbo的ExceptionFilter說起

我們來看看dubbo官方文檔的推薦處理方式是什么
建議使用異常匯報錯誤,而不是返回錯誤碼,異常信息能攜帶更多信息,并且語義更友好。如果擔心性能問題,在必要時,可以通過 override 掉異常類的 fillInStackTrace() 方法為空方法,使其不拷貝棧信息。查詢方法不建議拋出 checked 異常,否則調(diào)用方在查詢時將過多的 try...catch,并且不能進行有效處理。服務提供方不應將 DAO 或 SQL 等異常拋給消費方,應在服務實現(xiàn)中對消費方不關心的異常進行包裝,否則可能出現(xiàn)消費方無法反序列化相應異常。
dubbo在代碼中的處理方式是什么?
/** Copyright 1999-2011 Alibaba Group.* * Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at* * http://www.apache.org/licenses/LICENSE-2.0* * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/ package com.alibaba.dubbo.rpc.filter;import java.lang.reflect.Method;import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.extension.Activate; import com.alibaba.dubbo.common.logger.Logger; import com.alibaba.dubbo.common.logger.LoggerFactory; import com.alibaba.dubbo.common.utils.ReflectUtils; import com.alibaba.dubbo.common.utils.StringUtils; import com.alibaba.dubbo.rpc.Filter; import com.alibaba.dubbo.rpc.Invocation; import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.Result; import com.alibaba.dubbo.rpc.RpcContext; import com.alibaba.dubbo.rpc.RpcException; import com.alibaba.dubbo.rpc.RpcResult; import com.alibaba.dubbo.rpc.service.GenericService;/*** ExceptionInvokerFilter* <p>* 功能:* <ol>* <li>不期望的異常打ERROR日志(Provider端)<br>* 不期望的日志即是,沒有的接口上聲明的Unchecked異常。* <li>異常不在API包中,則Wrap一層RuntimeException。<br>* RPC對于第一層異常會直接序列化傳輸(Cause異常會String化),避免異常在Client出不能反序列化問題。* </ol>* * @author william.liangf* @author ding.lid*/ @Activate(group = Constants.PROVIDER) public class ExceptionFilter implements Filter {private final Logger logger;public ExceptionFilter() {this(LoggerFactory.getLogger(ExceptionFilter.class));}public ExceptionFilter(Logger logger) {this.logger = logger;}public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {try {Result result = invoker.invoke(invocation);if (result.hasException() && GenericService.class != invoker.getInterface()) {try {Throwable exception = result.getException();// 如果是checked異常,直接拋出if (! (exception instanceof RuntimeException) && (exception instanceof Exception)) {return result;}// 在方法簽名上有聲明,直接拋出try {Method method = invoker.getInterface().getMethod(invocation.getMethodName(), invocation.getParameterTypes());Class<?>[] exceptionClassses = method.getExceptionTypes();for (Class<?> exceptionClass : exceptionClassses) {if (exception.getClass().equals(exceptionClass)) {return result;}}} catch (NoSuchMethodException e) {return result;}// 未在方法簽名上定義的異常,在服務器端打印ERROR日志logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost()+ ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()+ ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), exception);// 異常類和接口類在同一jar包里,直接拋出String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface());String exceptionFile = ReflectUtils.getCodeBase(exception.getClass());if (serviceFile == null || exceptionFile == null || serviceFile.equals(exceptionFile)){return result;}// 是JDK自帶的異常,直接拋出String className = exception.getClass().getName();if (className.startsWith("java.") || className.startsWith("javax.")) {return result;}// 是Dubbo本身的異常,直接拋出if (exception instanceof RpcException) {return result;}// 否則,包裝成RuntimeException拋給客戶端return new RpcResult(new RuntimeException(StringUtils.toString(exception)));} catch (Throwable e) {logger.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost()+ ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()+ ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);return result;}}return result;} catch (RuntimeException e) {logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost()+ ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()+ ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);throw e;}}}

從上面我們可以看出,dubbo的處理方式主要是:

  • 如果provider實現(xiàn)了GenericService接口,直接拋出
  • 如果是checked異常,直接拋出
  • 在方法簽名上有聲明,直接拋出
  • 異常類和接口類在同一jar包里,直接拋出
  • 是JDK自帶的異常,直接拋出
  • 是Dubbo本身的異常,直接拋出
  • 否則,包裝成RuntimeException拋給客戶端
  • 接下來我們來測試一下

    我們自定義一個SelfException

    public class SelfException extends RuntimeException {public SelfException() {}public SelfException(String message, Throwable cause) {super(message, cause);}public SelfException(String message) {super(message);}public SelfException(Throwable cause) {super(cause);} }

    在服務端中拋出一個自定義的異常

    public class DemoServiceImpl implements DemoService {@Overridepublic String sayHello(String name) {System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());try {JSONObject.parse("aaa");}catch (Exception e){throw new SelfException(e);}return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();}}

    啟動服務對并對服務端進行訪問,我們可以發(fā)現(xiàn)

    服務端的日志

    Caused by: com.alibaba.fastjson.JSONException: syntax error, pos 1, json : aaaat com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1436)at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1322)at com.alibaba.fastjson.JSON.parse(JSON.java:152)at com.alibaba.fastjson.JSON.parse(JSON.java:162)at com.alibaba.fastjson.JSON.parse(JSON.java:131)at org.apache.dubbo.demo.provider.DemoServiceImpl.sayHello(DemoServiceImpl.java:34)... 29 more

    客戶端的日志

    java.lang.RuntimeException: org.apache.dubbo.demo.provider.SelfException: com.alibaba.fastjson.JSONException: syntax error, pos 1, json : aaa org.apache.dubbo.demo.provider.SelfException: com.alibaba.fastjson.JSONException: syntax error, pos 1, json : aaaat org.apache.dubbo.demo.provider.DemoServiceImpl.sayHello(DemoServiceImpl.java:36)at org.apache.dubbo.common.bytecode.Wrapper1.invokeMethod(Wrapper1.java)at org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:47)at org.apache.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:85)at org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker.invoke(DelegateProviderMetaDataInvoker.java:52)at org.apache.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:56)at org.apache.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:57)at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72)at org.apache.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:75)at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72)at org.apache.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:42)at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72)at org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:79)at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72)at org.apache.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:77)at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72)at org.apache.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:138)at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72)at org.apache.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72)at org.apache.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:39)at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:72)at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:114)at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:103)at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:200)at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:51)at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)at java.lang.Thread.run(Thread.java:745)

    可以看出, 我們這里并沒有拋出自定義的異常, 從而會導致客戶端沒有捕捉到自定義的異常.

    如何正確捕獲業(yè)務異常

    拋出一個自定義異常有這么麻煩嗎? 主要原因是dubbo沒有支持的原因.

    既然這樣,我們把dubbo變的支持不就可以了?

    是的.把源碼改一下就OK了.如下:

    String className = exception.getClass().getName(); if (className.startsWith("java.") || className.startsWith("javax.")) {return result; } // directly throw if it's dubbo exception if (exception instanceof RpcException) {return result; } //在這里添加我自己定義的異常類 if (exception instanceof SelfException) { return result; }

    或者直接將117行的RuntimeException替換成自己的自定義異常!這樣就從根本上解決了異常處理的問題.后續(xù)有其他問題,也可以直接修改.

    轉(zhuǎn)載于:https://www.cnblogs.com/luozhiyun/p/10251585.html

    總結

    以上是生活随笔為你收集整理的dubbo异常处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。