首页 > IT职业 > IT生活 > 声明式服务调用 Spring Cloud Feign
Spring Cloud 为了简化服务间的调用,在Ribbon的基础上进行了进一步的封装。单独抽出了一个组件,就是Spring Cloud Feign。在引入Spring Cloud Feign后,我们只需要创建一个接口并用注解的方式来配置它,即可完成对服务提供方的接口绑定。
Spring Cloud Feign具备可插拔的注解支持,并扩展了Spring MVC的注解支持。
下面我们来看一个具体的例子:
服务方具体的接口定义与实现代码如下:
调用方的使用代码如下:
通过上面的代码,我们可以看到,调用方通过feign进程远程服务调用的时候,非常简单,就向是在调用本地服务一样。
像之前的建立连接,构造请求,发起请求,获取响应,解析响应等等操作,对使用者来说都是透明化的,使用者不用关心服务是怎么实现调用的,直接使用即可。
其实
feign底层主要是靠动态代理来实现这整个服务的调用过程的。
主要逻辑如下:
因为Spring Cloud Feign的使用方式比Spring Cloud Ribbon更方便,所以一般项目中都是使用Feign,而且Feign还有继承特性,可以将远程服务接口继承过来然后再进行自己的个性化扩展。因此Feign的使用范围以及普及率更高一些。
在微服务架构中,我们将系统拆分成多个服务单元,各个服务之间通过服务注册与订阅的方式互相依赖。
我们以一个电商网站下单的过程来举例,在下单的业务操作过程中需要调用库存服务,支付服务,积分、物流等服务。 假设订单服务最多同一时间只能处理50个请求,这个时候如果积分服务挂了,那么每次订单服务去调用积分服务的时候,都会卡这么一段时间,然后才返回超时异常。
在这种场景下会有什么问题呢?
如果目前电商网站正在搞活动,进行抢购活动,下单的人非常多,这种高并发的场景下,订单服务的已经同时在处理50个下单请求了,并且都卡在了请求积分服务的过程中。订单服务已经没有能力去处理其他请求了。
那么其他服务再来调用订单服务时,发订单服务无响应,这样就导致订单服务也不可用了。然后其他依赖订单服务的服务,也最终会导致不可用。 这就是微服务架构中的服务雪崩。

就上图所示,如果多个服务之间相互调用,而不做任何保护措施的话,那么一个服务挂了,就会产生连锁反应,导致其他服务也挂了。
其实就算是积分服务挂了,也并不应该导致订单服务也挂了,积分服务挂了,我们可以跳过积分服务,或者是放一个默认值,然后继续往下走,等着积分服务恢复了,可以手动恢复一下数据。
那么Spring Cloud Hystrix就是解决这个问题的组件,他主要是起到熔断,隔离,降级的作用。
Spring Cloud Hystrix其实是会为每一个服务开辟一个线程池,然后每个线程池中的线程用于对服务的调用请求。这样就算是积分服务挂了,那也只是调用积分服务的线程池出现问题了,而其他服务的线程池还正常工作。 这就是服务的隔离。
这样订单服务在的调用积分服务的时候,如果发现有问题了,积分服务可以通过 Hystrix返回一个默认值(默认是5秒内20次调用失败就熔断)。这样订单服务就不用在这里卡住了,可以继续往下调用其他服务进行业务操作了。 这就是服务的熔断。
虽然说是积分服务挂了,并且也返回了默认值了,但是后续如果积分服务恢复了,想恢复数据怎么办呢?这个时候积分服务可以将姐收到的请求记录下来,或者是打到日志中,能为后面恢复数据提供依据就行。 这就是服务的降级。
整个过程大致如下图所示:

通过上面几个组件的结合使用,已经能够完成一个基本的微服务架构了。但是当一个系统中微服务的数量逐渐增多时,一些通用的逻辑,例如:权限校验机制,请求过滤,请求路由,限流等等,这些每个服务对外提供能力的时候都要考虑到的逻辑,就会变得冗余。
这个时候API网关的概念应运而生,它类似于面向对象设计模式中的Facade模式(门面模式/外观模式),所有的外部客户端访问都需要经过它来进行调度和过滤。主要实现请求路由、负载均衡、校验过滤、服务限流等功能。
Spring Cloud Zuul就是Spring Cloud提供的API网关组件,它 通过与Eureka进行整合,将自身注册为Eureka下的应用,从Eureka下获取所有服务的实例,来进行服务的路由。
Zuul还提供了一套过滤器机制,开发者可以自己指定哪些规则的请求需要执行校验逻辑,只有通过校验逻辑的请求才会被路由到具体服务实例上,否则返回错误提示。

Spring Cloud Zuul的依赖包
spring-cloud-starter-zuul本身就包含了对s
pring-cloud-starter-hystrix和
spring-cloud-starter-ribbon模块的依赖,所以Zuul天生就拥有线程隔离和断路器的自我保护功能,以及对服务调用的客户端负载功能。
Zuul的路由实现是通过Path和serviceId还实现的,path是一个http请求去除ip和端口号后的方法路径,例如:
http://192.168.20.12:9001/api-zuul/123,那么path就是
/api-zuul/123,Zuul在配置时支持模糊匹配,若123是动态参数,可以将path配置成
/pai-zuul/**,serviceId就是服务在Eureka中注册的服务名称。
有了统一的网关后,再做统一的鉴权、限流、认证授权、安全等方面的工作就会变的更加方便了。
上面总结了Spring Cloud的几个核心组件,其实Spring Cloud 除了这几个组件还有一些其他的组件,例如:
Spring Cloud Config;Spring Cloud Bus;Spring Cloud Stream;Spring Cloud Sleuth。主要是后面这些组件我们平时用的不多,而且对于微服务来说有些是有替代品的,所以我暂时就没有总结。还有一点毕竟我这次总结是为了解决面试的问题,所以后面如果在实际的工作中用到了剩下的这些组件,我会继续总结的。
好了,总结一下这次的几个组件的内容吧。
最后来一个整体的架构图,将各个组件串起来。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69993516/viewspace-2751007/ ,如需转载,请注明出处,否则将追究法律责任。