美文网首页
关于Feign的Fallback处理

关于Feign的Fallback处理

作者: bluexiii | 来源:发表于2017-09-16 09:54 被阅读4625次

    Feign的不恰当的fallback

    Feign的坑不少,特别与Hystrix集成之后。
    在微服务引入Feign后,上线不久后便发现,对于一个简单的查询类调用,在下游返回正常的"404-资源不存在"这种业务异常时,Feign也做了fallback,最终导致circuit break,引发平台告警。

    REST接口的设计

    为了解释这个问题,首先还是要从REST接口开始谈起。

    REST的一个缺点(也有人认为是优势),它只是一种依赖于HTTP的"风格",而没有明确的"规范",所以客户端和服务端之间,要自行达成某种"约定"。
    例如返回码,就要硬往HTTP STATUS上靠。

    关于返回码,公认的"最佳实践"大概是这样的:

    1. 如果业务处理成功,http status返回200、204等。如果有内容,BODY中直接返回内容(对象或数组都可以),不再有RPC时代的code/message这样的状态描述。如果没有内容,BODY直接空白,No News Is Good News。
    2. 如果业务处理失败,业务逻辑导致的,则http status返回4XX,BODY中返回报错信息,报错信息的统一格式大概是这样的:
    {
      "status": 409,  // 冗余字段,把http status再重复一遍
      "code": 888,  // 自定义的错误码
      "message": "foobar"  // 错误描述
    }
    
    1. 如果是其它未知错误,抛5XX,认为是服务器内部错误,而不是逻辑错误。

    所以对于APP/WEB等客户端来说,很简单,如果发现2XX,则认为成功,直接获取数据。如果非2XX,则是失败,直接取code和message,展现到前台。

    但是对于微服务之间的调用,就要区分是"4XX-业务逻辑异常",还是"5XX-服务器异常"了。。。

    REST返回码的选择

    下面详细讲一下HTTP STATUS的选择问题。

    关于HTTP返回码,看了很多参考(论战),"大概"可以这样选择:

    成功: 2XX系列

    • 200 OK // 查询、删除成功用这个
    • 201 CREATED // 新增、修改时用这个。且返回BODY中无任何信息。

    业务异常: 4XX系列

    • 400 BAD_REQUEST // 现在有很多人在业务异常时抛这个错。但400要慎重使用。稍后解释。
    • 404 NOT_FOUND // 查询不到结果时用这个
    • 403 FORBIDDEN // 这个也慎重使用。
    • 409 CONFLICT // 业务异常时,可以用这个。

    主机异常:5XX系列

    • 500 INTERNAL_SERVER_ERROR // 对于未知异常,统一用这个了
    • 503 SERVICE_UNAVAILABLE // Hystrix异常用这个

    什么时候应该Fallback

    2XX,成功,这个不用再讨论。
    5XX,也相当明确,直接Fallback,这个也不用讨论。
    4XX,可以一律认为是业务逻辑异常(或者更精确的说,可以认为4XX中的某几个是业务异常)。这时候,应该是用if/else来处理这个异常,而不应该动用Hystrix来Fallback。

    Feign在默认情况下,对于非2XX,都认为是异常。这个地方是有问题的。特别是对于404这种非常容易抛出的业务异常来说,没两下就circuit break了。

    Feign的Issue里已经有人提过这个问题,后面的版本中已经提供了一个参数:decode404

    可以看一下Feign的代码,位置在:
    ~/.m2/repository/io/github/openfeign/feign-core/9.5.0/feign-core-9.5.0.jar!/feign/SynchronousMethodHandler.class


    所以在Client上可以这样设置:

    @FeignClient(name = "marathon-lb", fallback = FooBarClientFallback.class, decode404 = true)
    @RequestMapping(value = "/foo/bar")
    public interface FooBarClient {
        ... ...
    }
    

    只需要加入decode404 = true这一个参数,Feign对于2XX和404 ,都不会走Fallback了。
    排除404,已经基本上够用了,如果想把409、400等status也加到例外中,可以重写一下Feign的errorDecoder。

    关于4XX错误

    刚才提到的,如果把2XX,另外加上4XX,全部认为是正常业务逻辑,都不走Fallback,可不可行? 我想最好不要这样很笼统的设置,要看情况。

    因为http status不全是服务端给出的,如果服务端与消费者之间隔着一些Nginx、HA、Kong这样的网关,那么情况可能就复杂了,网关也有可能抛出status。

    例如当某个微服务宕机之后,Kong网关会直接返回400,这种情况下,很明显是应当Fallback的。

    所以,在定义错误码时,要尽量避开400、403这种很溃常见的码,像409这样小众的,差不多可以放心使用。
    这样,调用方就可以有针对性的对某几个4XX的status进行单独配置,配置为业务异常。

    相关文章

      网友评论

          本文标题:关于Feign的Fallback处理

          本文链接:https://www.haomeiwen.com/subject/kgjysxtx.html