第5.1.3 SpringCloud Feign初步

dubbo是基于rpc的,实现系统调用,客户端只需要加载接口就可以,服务端负责具体实践。系统与系统之间的调用,就像自己调用自己一样,这样就非常方便了。而通过Rest API,则需要发送http请求,然后解析响应结果,这样通用的一个流程,spring又如何会放过呢,
33.服务之间的调用之RPC、Restful深入理解,RPC的性能显然比Rest要高,而且开发也较为简单。于是springcloud 之 Feign Rpc就此诞生了。
问题是Feign并不是真的RPC,而是伪的,让你在编写代码的时候,看起来像是真的一样方便。
1 pom.xml

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

2 添加@EnableFeignClients
这个是添加在客户端的调用中

@SpringBootApplication
@ComponentScan(basePackages = {"com.dzmsoft"})
@MapperScan(basePackages = { "com.dzmsoft.userserver.base.dao" })
@EnableEurekaClient
@EnableFeignClients
@Slf4j
@EnableAutoConfiguration
public class UserServerApplication {
    public static void main(String[] args) {
        try {
            SpringApplication.run(UserServerApplication.class, args);
        }finally {
            log.info("server start finish");
        }
    }
}

3 客户端调用
gateway-auth是要提供api服务端的spring.application.name, 请求路径jwt/verify就是服务端提供的restapi。

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(value = "gateway-auth")
public interface ServiceAuthFeign {

    @GetMapping("jwt/verify")
    String getInfo(@RequestParam(value = "token") String token);

}

4 服务端的代码
服务端的代码并没有什么特别,就是不同的controller而已

@GetMapping("verify")
    public ResponseEntity<String> verify(@RequestParam(value = "token") String token) throws Exception{
        try {
            if(stringRedisTemplate.opsForValue().get(token)!=null){
                throw new UserTokenException("token失效,请重新登录");
            }
            IJWTInfo info = authService.validate(token);
            return ResponseEntity.ok(info.getId());
        } catch (ExpiredJwtException ex){
            throw new UserTokenException("User token expired!");
        }catch (SignatureException ex){
            throw new UserTokenException("User token signature error!");
        }catch (IllegalArgumentException ex){
            throw new UserTokenException("User token is null or empty!");
        }
    }

使用起来,就像上面那么简单。
杨恩雄的《疯狂Spring Cloud微服务架构实战》介绍Feign时,介绍了多种调用REST服务的方式,第一是CXF,CXF是一个webservice框架,那么webservice与REST有什么关系呢?
先了解一下webservice的发展历史,SOAP和WebService的那些事,现有了SOAP,这个协议是厂商之间协定的一个标准,再看看HTTP协议是由互联网工程工作小组制定的,所以可以想象SOAP的确夹杂着厂商的技术壁垒,而HTTP则不然。于是就发展出来了支持REST的webservice。
5 feign超时问题
使用feign过程中,最郁闷的是timeout问题,设置各种配置均没能解决.

2021-07-27 18:05:18.352 ERROR c.w.gateway.common.handler.GlobalExceptionHandler - OpenapiServiceFeign#validate(String) timed-out and fallback failed.
com.netflix.hystrix.exception.HystrixRuntimeException: OpenapiServiceFeign#validate(String) timed-out and fallback failed.
	at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:832)
	at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:807)
	at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140)
	at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
	at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
	at com.netflix.hystrix.AbstractCommand$DeprecatedOnFallbackHookApplication$1.onError(AbstractCommand.java:1472)
	at com.netflix.hystrix.AbstractCommand$FallbackHookApplication$1.onError(AbstractCommand.java:1397)
	at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
	at rx.observers.Subscribers$5.onError(Subscribers.java:230)
	at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:44)
	at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:28)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
	at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
	at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
	at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
	at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
	at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:142)
	at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
	at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
	at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$1.run(AbstractCommand.java:1142)
	at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:41)
	at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:37)
	at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable.run(HystrixContextRunnable.java:57)
	at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$2.tick(AbstractCommand.java:1159)
	at com.netflix.hystrix.util.HystrixTimer$1.run(HystrixTimer.java:99)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.runAndReset$$$capture(FutureTask.java:308)
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.util.concurrent.TimeoutException: null
	at com.netflix.hystrix.AbstractCommand.handleTimeoutViaFallback(AbstractCommand.java:997)
	at com.netflix.hystrix.AbstractCommand.access$500(AbstractCommand.java:60)
	at com.netflix.hystrix.AbstractCommand$12.call(AbstractCommand.java:609)
	at com.netflix.hystrix.AbstractCommand$12.call(AbstractCommand.java:601)
	at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140)
	... 16 common frames omitted
2021-07-27 18:07:08.418 INFO  c.n.d.shared.resolver.aws.ConfigClusterResolver - Resolving eureka endpoints via configuration
2021-07-27 18:12:08.419 INFO  c.n.d.shared.resolver.aws.ConfigClusterResolver - Resolving eureka endpoints via configuration

5.1 设置超时时间
【问题排查】开启 SpringFeign 的 Hystrix 熔断器出现 timed-out and no fallback available 错误
不需要熔断服务,关闭掉Hystrix

feign:
  hystrix:
    enabled: false

但开放平台是需要开启Hystrix ,在客户端的yml中配置,就调通了,这里没有使用ribbon与hystrix混搭的方式

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 5000  #熔断超时时间

接下来

Caused by: feign.RetryableException: connect timed out executing POST http://openapi-server/feignapi/validate?phoneNumber=17612737265
	at feign.FeignException.errorExecuting(FeignException.java:213)
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:115)
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:80)
	at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:109)
	at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:302)
	at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:298)
	at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
	... 27 common frames omitted
Caused by: java.net.SocketTimeoutException: connect timed out

这里增加下面client的超时配置

feign:
  hystrix:
    enabled: true
  client:
    config:
      default:
        connectTimeout: 10000
        readTimeout: 10000
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

warrah

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值