我正在构建一个SpringBoot微服务,它调用另一个微服务,当然想使用Hystrix和Feign客户机,这两个客户机都包含在Spring Cloud中。我使用的是camden.sr5版本。
对于任何超时、连接失败和来自Feign的50倍响应代码,我希望Hystrix踢进并正常工作:跳闸断路器和调用回退(如果配置)等。它在默认情况下这样做,所以我很好。
使用以下代码开箱即用:
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.hateoas.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(name = "dog-service", url = "http://...")
public interface DogsFeignClient {
@RequestMapping(method = RequestMethod.POST, path = "/dogs")
Resource<Dog> createDog(Dog dog);
}
生成这个异常,它不能很好地将40x响应传递回调用方:
com.netflix.hystrix.exception.HystrixRuntimeException: DogsFeignClient#createDog(Dog) failed and no fallback available.
at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:805) ~[hystrix-core-1.5.6.jar:1.5.6]
....lines ommited for brevity....
Caused by: feign.FeignException: status 400 reading DogsFeignClient#createDog(Dog); content:
{
"errors" : [ {
"entity" : "Dog",
"property" : "numberOfLegs",
"invalidValue" : "3",
"message" : "All dogs must have 4 legs"
} ]
}
at feign.FeignException.errorStatus(FeignException.java:62) ~[feign-core-9.3.1.jar:na]
at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:91) ~[feign-core-9.3.1.jar:na]
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:138) ~[feign-core-9.3.1.jar:na]
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76) ~[feign-core-9.3.1.jar:na]
at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:108) ~[feign-hystrix-9.3.1.jar:na]
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:301) ~[hystrix-core-1.5.6.jar:1.5.6]
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:297) ~[hystrix-core-1.5.6.jar:1.5.6]
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46) ~[rxjava-1.1.10.jar:1.1.10]
... 26 common frames omitted
当然,我可以查看com.netflix.hystrix.exception.hystrixruntimeException
、case
字段,其中包含feign.feignException
,并且隐藏在描述中的是JSON响应本身,包含换行符等。但是feign.FeignException
的case
字段是对其本身的引用。是否有一种方法可以传播更深层次的异常而不是HystrixRuntimeException?
还有一种方法可以让下游服务的响应包含原始主体,这样我就不必解构嵌套异常的消息字段了吗?
这可以使用单独的配置来实现,该配置将在HystrixBadRequestException
的子类中包装400个,并将它们抛给客户端代码。这些例外不影响断路器的状态--如果电路关闭,它将保持关闭,如果它打开,它将保持开放。
@FeignClient(name = "dog-service",
url = "http://...",
configuration=FeignPropagateBadRequestsConfiguration.class)
public interface DogsFeignClient {
@RequestMapping(method = RequestMethod.POST, path = "/dogs")
Resource<Dog> createDog(Dog dog);
}
其中FeignPropagateBadRequestsConfiguration
为
@Configuration
public class FeignSkipBadRequestsConfiguration {
@Bean
public ErrorDecoder errorDecoder() {
return (methodKey, response) -> {
int status = response.status();
if (status == 400) {
String body = "Bad request";
try {
body = IOUtils.toString(response.body().asReader());
} catch (Exception ignored) {}
HttpHeaders httpHeaders = new HttpHeaders();
response.headers().forEach((k, v) -> httpHeaders.add("feign-" + k, StringUtils.join(v,",")));
return new FeignBadResponseWrapper(status, httpHeaders, body);
}
else {
return new RuntimeException("Response Code " + status);
}
};
}
}
FeignBadResponseWrapper
是
@Getter
@Setter
public class FeignBadResponseWrapper extends HystrixBadRequestException {
private final int status;
private final HttpHeaders headers;
private final String body;
public FeignBadResponseWrapper(int status, HttpHeaders headers, String body) {
super("Bad request");
this.status = status;
this.headers = headers;
this.body = body;
}
}
这有点麻烦,您只能在errordecoder
中获得响应正文,因为在此之后流将被关闭。但是使用此方法,您可以将响应数据抛出给客户端代码,而不会影响电路:
try {
return dogsFeignClient.createDog(dog);
} catch (HystrixBadRequestException he) {
if (he instanceof FeignBadResponseWrapper) {
// obtain data from wrapper and return it to client
} else {
// return basic error data for other exceptions
}
}
我正在使用feign创建一个REST客户端。我有我的电话工作,但我想添加一些超时支持,我有一段时间,弄清楚如何做到这一点。 Feign的文档中说:“要将Hystrix与Feign一起使用,请将Hystrix模块添加到类路径中,然后使用HystrixFeign构建器。”好了,现在我有了这个: 现在我的所有方法都在返回HystrixCommands,我可以执行或排队,但仍然看不到如何配置它们。 但是我
问题内容: 此sql代码抛出一个 WHERE中不允许使用聚合函数 如何避免此错误? 问题答案: 用替换子句,如下所示: 与相似,两者均用于过滤结果记录,但用于过滤汇总数据(使用时)。
我在javascript中使用Reactjs和通过AJAX使用API。我们如何解决这个问题?以前我使用CORS工具,但现在我需要启用CORS。
问题内容: 尝试设置密钥时出现“不允许OOM命令”, 通过“ volatile-lru” 设置为500M ,我为发送给redis的每个密钥设置TTL。 命令返回: 如果maxmemory设置为500M,我怎么达到809M? 命令没有显示任何键空间,这怎么可能? 返回“(空列表或集合)”,我试图更改数据库号,但仍未找到键。 这是info命令输出: 问题答案: 您是否有可能更改了数据库数量?如果您使用
从终端创建myDSL语法 起点,包含行列表 每一行都可以选择以LABEL开始,然后以关键字开始 这个语法适用于单引号中有空格的字符串。但是它有很多错误/警告 警告(200):/组织。xtext。实例mydsl/src gen/org/xtext/example/mydsl/parser/antlr/internal/InternalMyDsl。g:309:3:决策可以使用多个选项匹配输入,例如“R
我正试图让spring slueth通过我们的系统提供追踪身份。 在检查其他服务的日志时,我注意到正在生成新的ID。