1. 程式人生 > >如何全域性捕捉 eureka 通過 Feign 遠端調用出現的異常

如何全域性捕捉 eureka 通過 Feign 遠端調用出現的異常

萬事皆有因

玩過 springcloud 的微服務架構的小夥伴們都知道,在我們通過 eureka 遠端呼叫其他的微服務的時候,防止網路抖動或者程式異常等情況,往往會加上 hystrix 斷路器對異常進行處理,但是往往在處理的時候一般都是記錄一些日誌高速開發者哪裡出問題了,引數是什麼,又或者其他的處理

然而,很多人使用 Feign 的時候 rollback 都是繼承被呼叫的 FeignClient 的一個子類,然後裡面重寫介面的方法,記錄日誌等等操作。

想想一下,其實處理這些 rpc 異常的方式基本差不多,然後每一個方法都需要重新寫一遍,強迫症嚴重的人肯定不允許這樣的事情發生,那麼我們該如何做到通過一個方法將這些錯誤日誌將調不同介面方法異常打印出來呢?

突然靈光一閃

該怎麼做呢?當時我想啊,若能動態生成其子類的方法是不是可以達到目的呢?於是通過動態代理去實現,下面給出程式碼。

  • rollback 工廠類

import com.qts.agent.web.util.ReflectionUtil;
import feign.hystrix.FallbackFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Proxy;
/** * 基礎的遠端異常捕捉 * * @author 阿導 * @CopyRight 萬物皆導 * @created 2018年08月09日 14:56:00 * @Modified_By 阿導 2018/8/9 14:56 */ @Component public class BaseFailedFactory<T> implements FallbackFactory<T> { /** * 沒別的意思,就想記一個日誌 */ private Logger logger = LoggerFactory.getLogger(this.getClass())
; @Override public T create(Throwable throwable) { T newProxyInstance = (T) Proxy.newProxyInstance( getEntityClass().getClassLoader(), new Class[] { getEntityClass() }, new MethodProxy(logger)); return newProxyInstance; } /** * 獲取需要操作的實體類class * * @return */ private <T> Class<? extends T> getEntityClass() { return ReflectionUtil.getSuperClassGenricType(getClass()); } }
  • 代理方法類
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 方法代理
 *
 * @author 阿導
 * @CopyRight 萬物皆導
 * @created 2018/8/9 15:43
 * @Modified_By 阿導 2018/8/9 15:43
 */
public class MethodProxy implements InvocationHandler {
  private Logger logger;
  
  public MethodProxy(Logger logger) {
    this.logger = logger;
  }
  
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) {
    // 執行之前
    if (Object.class.equals(method.getDeclaringClass())) {
      try {
        return method.invoke(this, args);
      } catch (Throwable t) {
        t.printStackTrace();
      }
    } else {
      return run(method, args);
    }
    // 執行之後
    return null;
  }
  
  /**
   *
   *
   * @author 阿導
   * @time 2018/8/9 16:35
   * @CopyRight 萬物皆導
   * @param method
   * @param args
   * @return
   */
  private Object run(Method method, Object[] args) {
    logger.error("遠端呼叫失敗,目標:" + method.getDeclaringClass());
    logger.error("引數:" + JSON.toJSONString(args));
    return null;
  } 
}


  • 反射工具類獲取泛型的具體的類

就那麼輕輕一測試

測試就不用說了哈,要麼是呼叫的服務宕機,要麼使其異常,看是否能處理,大家明白了嗎?若有不清楚的地方,麻煩再留言區留下金言玉語,當然寫的不足之處,還望海涵。

需要雲伺服器的不要錯過優惠