Spring cloud netflix 和 HystrixObservable --> JsonMappingException

Posted

技术标签:

【中文标题】Spring cloud netflix 和 HystrixObservable --> JsonMappingException【英文标题】:Spring cloud netflix and HystrixObservable --> JsonMappingException 【发布时间】:2017-07-08 07:07:22 【问题描述】:

代码见我的小4类github project

我正在使用 Spring FeignClients 连接到休息服务。这是 Feign 客户端在其基本(非异步)形式中的样子:

@FeignClient(value="localhost:8080/products", decode404 = true)
public interface ProductClient 
    @RequestMapping(value="/id")
    Product getById(@PathVariable("id") String id);

现在我想使用 Observable 异步执行此操作。 Spring 文档中严重缺乏这方面的信息,只有small paragraph 告诉您使用 HystrixCommand。仅此而已,没有解释,没有示例代码。

在另一篇博文中,有人告诉我改用 HystrixObservable。所以我尝试了:

@FeignClient(value="localhost:8080/products", decode404 = true)
public interface ProductClient 
    @RequestMapping(value="/id")
    HystrixObservable<Product> getById(@PathVariable("id") String id);

无论哪种方式,使用 HystrixCommand 或 HystrixObservable,它都会向我抛出错误: com.fasterxml.jackson.databind.JsonMappingException: 无法构造 com.netflix.hystrix.HystrixObservable 的实例

我理解为什么会出现这个错误,因为 Spring Boot 会自动将 Decoder 附加到 FeignClient 以使用 Jackson 反序列化响应。并且将响应反序列化为的类型是从返回值派生的。

我可以尝试配置自定义解码器或手动构建 Feign 客户端,但这违背了 Spring Boot 的全部目的:它自动工作(尽管在这里和那里进行了一些配置)。

所以我的问题是:这应该如何工作?

【问题讨论】:

如documentation 所示,您需要以不同方式构造客户端(通过HystrixFeign)。 是的,可以手动构建 Feign 客户端。但我的问题是关于 Spring + Feign。那么如何让 Spring 生成合适的 Feign 客户端呢? Spring 文档建议它可以,但是省略了一些重要的细节。这个blog post 也暗示了我在做什么。 @AnnevanderBom 你能成功吗? @BogdanTimofeev 不幸的是没有。 【参考方案1】:

如果您将返回类型指定为 HystrixCommand&lt;Product&gt; 或 RxJava 的 Observable&lt;Product&gt;Single&lt;Product&gt; 而不是 HystrixObservable&lt;Product&gt;,它应该可以工作。

我认为使用HystrixObservable 不起作用的原因是因为它是一个接口,并且默认情况下Jackson 不会映射到接口等抽象类型,正如您可能在堆栈跟踪中看到的那样:

> abstract types either need to be mapped to concrete types, have custom
> deserializer, or contain additional type information

不过,HystrixCommandHystrixObservable 接口的一个实现,因此 Jackson 可以轻松映射到它。

如果您查看Feign's Hystrix module 中的HystrixInvocationHandler,您将看到它能够返回的其他类型;我在上面列出的那些以及 RxJava 的 Completable。 Tassos Bassoukos 链接的文档也列出了这些类型。

如果您正在寻找异步且非阻塞的东西,可能值得一试 Feign Vertx,因为我相信 Feign 可以是异步但阻塞的。关于非阻塞Feign的讨论是here。

希望有帮助!

【讨论】:

感谢您的回答。 Jackson 既不应该反序列化 HystrixCommand,也不应该反序列化 HystrixObservable,而是反序列化 Product,因为这是响应中的有效负载。请求中的返回值必须在某处进行反序列化,并且将其反序列化为的类型取自方法的返回类型(在本例中为 HystrixObservable)。但这是错误的策略。它应该查看泛型类型。由于类型擦除,这在运行时相当困难。【参考方案2】:

如果有人在升级到 spring-cloud:1.3.+ 后开始出现此错误,请确保您已启用 hystrix-feign。

feign.hystrix.enabled=true

添加这个是为了让 feign 默认情况下不会在 hystrix 命令中包装调用。

https://github.com/spring-cloud/spring-cloud-netflix/issues/1277

【讨论】:

以上是关于Spring cloud netflix 和 HystrixObservable --> JsonMappingException的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud Netflix(网飞)

随手记录关于spring-cloud-starter-eureka-server 和 spring-cloud-starter-netflix-eureka-server

Spring Cloud 入门教程:和RabbitMQ的整合 -- 消息总线Spring Cloud Netflix Bus

Netflix之后,如何用Spring Cloud 新组件构建微服务架构?

spring-cloud-starter-eureka-server 和 spring-cloud-starter-netflix-eureka-server的区别

Spring cloud netflix 和 HystrixObservable --> JsonMappingException