伪造客户端并 Spring 重试
Feign client and Spring retry
我有一个 restful 服务使用 Spring Cloud Feign 客户端调用外部服务
@FeignClient(name = "external-service", configuration = FeignClientConfig.class)
public interface ServiceClient {
@RequestMapping(value = "/test/payments", method = RequestMethod.POST)
public void addPayment(@Valid @RequestBody AddPaymentRequest addPaymentRequest);
@RequestMapping(value = "/test/payments/{paymentId}", method = RequestMethod.PUT)
public ChangePaymentStatusResponse updatePaymentStatus(@PathVariable("paymentId") String paymentId,
@Valid @RequestBody PaymentStatusUpdateRequest paymentStatusUpdateRequest);
}
我在过去 3 个月的日志文件中注意到以下故障 3-4 次:
json.ERROR_RESPONSE_BODY:Connection refused executing POST
http://external-service/external/payments json.message:Send Payment
Add Payment Failure For other reason: {ERROR_RESPONSE_BODY=Connection
refused executing POST http://external-service/external/payments,
EVENT=ADD_PAYMENT_FAILURE, TRANSACTION_ID=XXXXXXX} {}
json.EVENT:ADD_PAYMENT_FAILURE
json.stack_trace:feign.RetryableException: Connection refused
executing POST http://external-service/external/payments at
feign.FeignException.errorExecuting(FeignException.java:67) at
feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:104)
at
feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)
at
feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
是否可以在 Feign 客户端上添加 Spring 重试。
我想用
注释 addPayment
操作
@Retryable(value = {feign.RetryableException.class }, maxAttempts = 3, backoff = @Backoff(delay = 2000, multiplier=2))
但这不可能,我还有什么其他选择?
您可以在 FeignClientConfig
中添加一个 Retryer
@Configuration
public class FeignClientConfig {
@Bean
public Retryer retryer() {
return new Custom();
}
}
class Custom implements Retryer {
private final int maxAttempts;
private final long backoff;
int attempt;
public Custom() {
this(2000, 3);
}
public Custom(long backoff, int maxAttempts) {
this.backoff = backoff;
this.maxAttempts = maxAttempts;
this.attempt = 1;
}
public void continueOrPropagate(RetryableException e) {
if (attempt++ >= maxAttempts) {
throw e;
}
try {
Thread.sleep(backoff);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
}
@Override
public Retryer clone() {
return new Custom(backoff, maxAttempts);
}
}
更新了基于 Retryer.Default
.
的示例 Retryer
示例配置
如果您使用的是功能区,则可以设置属性,您可以使用以下属性进行重试:
myapp.ribbon.MaxAutoRetries=5
myapp.ribbon.MaxAutoRetriesNextServer=5
myapp.ribbon.OkToRetryOnAllOperations=true
注意:"myapp" 是您的服务 ID。
查看此 Github implementation 工作示例
如果对某人有帮助,请添加。我正在使用 feign 重置连接,因为该端口上有一些未知进程 运行。
尝试更改端口。 Refer this to find the process running on a port
我通过在 ServiceClient 之上创建一个包装器解决了这个问题
@Configuration
public class ServiceClient {
@Autowired
ServiceFeignClient serviceFeignClient;
@Retryable(value = { ClientReprocessException.class }, maxAttemptsExpression = "#{${retryMaxAttempts}}", backoff = @Backoff(delayExpression = "#{${retryDelayTime}}"))
public void addPayment( AddPaymentRequest addPaymentRequest){
return serviceFeignClient.addPayment(addPaymentRequest);
}
}
刚新建一个构造函数Default
@Configuration
public class FeignClientConfig {
@Bean
public Retryer retryer() {
return new Retryer.Default(100, 2000, 3);
}
}
我准备了一篇博客 post 关于使用 Spring Retry with Feign Client 方法。您可以考虑检查 Post。 post.
中解释了所有步骤
这是我的配置。在 spring boot 2.2.0.RELEASE 中测试正常
spring云Hoxton.M3.
feign.hystrix.enabled=true
MY-SPRING-API.ribbon.MaxAutoRetries=2
MY-SPRING-API.ribbon.MaxAutoRetriesNextServer=2
MY-SPRING-API.ribbon.OkToRetryOnAllOperations=true
MY-SPRING-API.ribbon.retryableStatusCodes=404,500
feign.client.config.PythonPatentClient.connectTimeout=500
feign.client.config.PythonPatentClient.readTimeout=500
hystrix.command.PythonPatentClient#timeTest(String).execution.isolation.thread.timeoutInMilliseconds=5000
java 代码是:
@FeignClient(name = "MY-SPRING-API",configuration = {PythonPatentConfig.class},fallbackFactory = FallBack.class)
public interface PythonPatentClient
@RequestLine("GET /test?q={q}")
void timeTest(@Param("appNo") String q);
控制器是:
@RequestMapping(value = "/test",method = {RequestMethod.POST,RequestMethod.GET})
public Object test() throws InterruptedException {
log.info("========important print enter test========");
TimeUnit.SECONDS.sleep(10L);
pom.xml 添加:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
可选:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
@EnableRetry
@SpringBootApplication
public class ApiApplication
这是文档 :
我有一个 restful 服务使用 Spring Cloud Feign 客户端调用外部服务
@FeignClient(name = "external-service", configuration = FeignClientConfig.class)
public interface ServiceClient {
@RequestMapping(value = "/test/payments", method = RequestMethod.POST)
public void addPayment(@Valid @RequestBody AddPaymentRequest addPaymentRequest);
@RequestMapping(value = "/test/payments/{paymentId}", method = RequestMethod.PUT)
public ChangePaymentStatusResponse updatePaymentStatus(@PathVariable("paymentId") String paymentId,
@Valid @RequestBody PaymentStatusUpdateRequest paymentStatusUpdateRequest);
}
我在过去 3 个月的日志文件中注意到以下故障 3-4 次:
json.ERROR_RESPONSE_BODY:Connection refused executing POST http://external-service/external/payments json.message:Send Payment Add Payment Failure For other reason: {ERROR_RESPONSE_BODY=Connection refused executing POST http://external-service/external/payments, EVENT=ADD_PAYMENT_FAILURE, TRANSACTION_ID=XXXXXXX} {} json.EVENT:ADD_PAYMENT_FAILURE json.stack_trace:feign.RetryableException: Connection refused executing POST http://external-service/external/payments at feign.FeignException.errorExecuting(FeignException.java:67) at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:104) at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76) at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
是否可以在 Feign 客户端上添加 Spring 重试。 我想用
注释addPayment
操作
@Retryable(value = {feign.RetryableException.class }, maxAttempts = 3, backoff = @Backoff(delay = 2000, multiplier=2))
但这不可能,我还有什么其他选择?
您可以在 FeignClientConfig
Retryer
@Configuration
public class FeignClientConfig {
@Bean
public Retryer retryer() {
return new Custom();
}
}
class Custom implements Retryer {
private final int maxAttempts;
private final long backoff;
int attempt;
public Custom() {
this(2000, 3);
}
public Custom(long backoff, int maxAttempts) {
this.backoff = backoff;
this.maxAttempts = maxAttempts;
this.attempt = 1;
}
public void continueOrPropagate(RetryableException e) {
if (attempt++ >= maxAttempts) {
throw e;
}
try {
Thread.sleep(backoff);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
}
@Override
public Retryer clone() {
return new Custom(backoff, maxAttempts);
}
}
更新了基于 Retryer.Default
.
Retryer
示例配置
如果您使用的是功能区,则可以设置属性,您可以使用以下属性进行重试:
myapp.ribbon.MaxAutoRetries=5
myapp.ribbon.MaxAutoRetriesNextServer=5
myapp.ribbon.OkToRetryOnAllOperations=true
注意:"myapp" 是您的服务 ID。
查看此 Github implementation 工作示例
如果对某人有帮助,请添加。我正在使用 feign 重置连接,因为该端口上有一些未知进程 运行。 尝试更改端口。 Refer this to find the process running on a port
我通过在 ServiceClient 之上创建一个包装器解决了这个问题
@Configuration
public class ServiceClient {
@Autowired
ServiceFeignClient serviceFeignClient;
@Retryable(value = { ClientReprocessException.class }, maxAttemptsExpression = "#{${retryMaxAttempts}}", backoff = @Backoff(delayExpression = "#{${retryDelayTime}}"))
public void addPayment( AddPaymentRequest addPaymentRequest){
return serviceFeignClient.addPayment(addPaymentRequest);
}
}
刚新建一个构造函数Default
@Configuration
public class FeignClientConfig {
@Bean
public Retryer retryer() {
return new Retryer.Default(100, 2000, 3);
}
}
我准备了一篇博客 post 关于使用 Spring Retry with Feign Client 方法。您可以考虑检查 Post。 post.
中解释了所有步骤这是我的配置。在 spring boot 2.2.0.RELEASE 中测试正常 spring云Hoxton.M3.
feign.hystrix.enabled=true
MY-SPRING-API.ribbon.MaxAutoRetries=2
MY-SPRING-API.ribbon.MaxAutoRetriesNextServer=2
MY-SPRING-API.ribbon.OkToRetryOnAllOperations=true
MY-SPRING-API.ribbon.retryableStatusCodes=404,500
feign.client.config.PythonPatentClient.connectTimeout=500
feign.client.config.PythonPatentClient.readTimeout=500
hystrix.command.PythonPatentClient#timeTest(String).execution.isolation.thread.timeoutInMilliseconds=5000
java 代码是:
@FeignClient(name = "MY-SPRING-API",configuration = {PythonPatentConfig.class},fallbackFactory = FallBack.class)
public interface PythonPatentClient
@RequestLine("GET /test?q={q}")
void timeTest(@Param("appNo") String q);
控制器是:
@RequestMapping(value = "/test",method = {RequestMethod.POST,RequestMethod.GET})
public Object test() throws InterruptedException {
log.info("========important print enter test========");
TimeUnit.SECONDS.sleep(10L);
pom.xml 添加:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
可选:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
@EnableRetry
@SpringBootApplication
public class ApiApplication
这是文档 :