这里我们继续学习SpringCloud中的Feign组件,我们这里强烈建议使用《SpringCloud之Hystrix使用高级篇》中的环境
1.首先我这里有spring-cloud-parent pom工程
2.spring-cloud-eureka-server Eureka Server 子工程 这里端口我们使用90开头
我们这里集群由两个服务实例组成,分别是9090与9091端口
3.spring-cloud-user-service-consumer 用户服务 (也就是咱们的服务消费者)这里端口我们使用80 开头 ,
我们这个用户服务现在这里有两个实例,分别是8080与8081
4.spring-cloud-order-service-provider 订单提供服务 (服务提供者) 这里端口我们使用70开头
我们订单服务提供着也由两个实例组成,分别是7070与7071
如果不想使用该环境,可以根据架构图来搭建自己的环境,这里我使用的spring-cloud版本是Greenwich.RELEASE。
我们都知道,Fegin这个组件内部是 RestTemplate+Ribbon+Hystrix组成的,我们在使用Fegin的时候就可以将之前添加Hystrix依赖给去掉了,接下来我们就简单使用一下Fegin
使用Fegin主要是需要我们的服务调用者,也就是服务消费者项目,在这里是spring-cloud-user-service-consumer项目。
首先我们需要在项目的pom.xml中引入Fegin的相关依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
如果我们服务中引入了Hystrix的相关依赖,这个需要去掉或者注释掉,因为我们Fegin的依赖中会自动引入。
我们需要在服务提供者的主启动类添加@EnableFeignClients 注解,表示开启Fegin,当然,如果我们主启动类上面有有关于熔断器的注解可以注释掉。
还有之前咱们写的RestTemplateConfiguration 配置类这个是需要留着的。
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
这里我们在服务调用者新建一个service包,然后根据服务提供者的接口,写了一个FeginClient接口,这里可以直接将 服务提供者接口controller中的method 搬过来,然后去掉方法体就可以了
@FeignClient(name = "spring-cloud-order-service-provider") // 这里这个name 需要填写 请求的服务提供者的注册到Eureka Server上面的服务名
@RequestMapping("/order/data") // 这里你服务提供者接口controller 啥样 可以照着搬过来,当然也可以写到FeignClient注解的path属性上。
public interface OrderStatisticFeginClient {
// 请求路径,FeginClient增加了对Springmvc的支持,所以可以直接将服务提供者接口controller 方法搬过来,然后去掉方法体
@GetMapping("/getTodayFinishOrderNum/{id}")
public Integer getTodayFinishOrderNum(@PathVariable("id") Integer id);
}
这里我们需要对UserCenterController做改造,当然也可以新写一个。如果用之前的UserCenterController 就需要将之前的Hystrix的一些注释掉。我们的controller只需要注入咱们上面写的Fegin Client接口,然后调用就可以了,下面提供了完整的UserCenterController代码。
@RestController
@RequestMapping("/user/data")
public class UserCenterController {
// 注入咱们的Fegin Client接口
@Autowired
private OrderStatisticFeginClient orderStatisticFeginClient;
@GetMapping("/getTodayStatistic/{id}")
public Integer getTodayStatistic(@PathVariable("id") Integer id){
// 直接调用
Integer todayFinishOrderNum = orderStatisticFeginClient.getTodayFinishOrderNum(id);
return todayFinishOrderNum;
}
}
这里附上服务提供者也就是我们的订单服务controller代码
@RestController
@RequestMapping("/order/data")
public class OrderStatisticServiceController {
@Value("${server.port}")
private Integer port;
/**
* 根据用户id获取今日完单数
* @param id 用户ID
* @return 完单数
*/
@GetMapping("/getTodayFinishOrderNum/{id}")
public Integer getTodayFinishOrderNum(@PathVariable("id") Integer id){
return port;
}
}
这里我们需要把Eureka Server 提起来分别是9090 与9091端口,然后将我们的两个服务提供者实例提起来分别是7070 与7071端口,最后将服务调用者提起来,这里我们这里提一个就可以了8080端口。
我们可以看到服务都起来了,然后接着浏览器输入http://127.0.0.1:8080/user/data/getTodayStatistic/100
调用接口测试。我们可以看到已经可以调通了
我们知道Fegin里面整合了Ribbon,然后我们就可以通过个性化配置来使用Ribbon的一些特性,我们的Fegin调用默认超时时间是1秒,但是有些很复杂的业务处理往往要高于1秒的,这时候可以设置Ribbon的超时时间,然后Fegin就会以Ribbon的超时时间为准了。
我们需要在项目的配置文件(application.yml)中添加关于Ribbon的配置
# 单独对这个spring-cloud-order-service-provider 服务的调用生效,如果想配置全局生效的话可以不用写这个服务名,
spring-cloud-order-service-provider:
ribbon:
# 这个是连接超时时间
ConnectTimeout: 1000
# 这个是服务处理请求超时时间
ReadTimeout: 5000
# 对所有的操作进行重试工作
OkToRetryOnAllOperations: true
# 当超时的时候,最大重试次数,这里是设置了3次,不包含第一次请求那次 ,这个请求重试是在超时服务上试
MaxAutoRetries: 2
# 如果在调用当前服务重试次数没了,就换个服务
MaxAutoRetriesNextServer: 1
#负载均衡策略
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
为了演示方便我们需要修改下服务提供者的接口代码,需要将7070端口的sheep 10s ,7071端口的服务不变。
@GetMapping("/getTodayFinishOrderNum/{id}")
public Integer getTodayFinishOrderNum(@PathVariable("id") Integer id){
System.out.println("我是"+port);
if (port==7070){
try {// 睡眠10s
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return port;
}
重启服务提供者与服务消费者服务并测试
我这里第一次调用访问到了7071,然后我又调用了一次
我们可以看到在7070 访问了3次,1次是我手动调用,然后2次是超时重试,再来看下7071的日志信息
7071 第一次是我手动调用的,然后第2次是重试完7070服务还不行,然后访问的7071。从接口调用返回的结果也是这样的
Fegin也是集成了咱们熔断器,接下来我们就看看对于熔断器的配置
我们需要在项目配置类appliaction.yml 中开启对熔断器的支持
# 开启Fegin对熔断器的支持
feign:
hystrix:
enabled: true
接着配置熔断器的一些参数,其实这里熔断器的一些参数还跟咱们之前Hystirx学习中配置文件配置一样
我们这里配置一个熔断器的超时时间
hystrix:
command:
default:
execution:
isolation:
thread:
# 配置熔断器的超时时间,我这里配置了12s
timeoutInMilliseconds: 12000
当我们开启熔断器后,Fegin里面的方法都会被进行管理,一旦出现熔断,就会服务降级,也就是执行咱们的服务降级方法fallback方法。
下面我们需要编写fallback处理。
我们需要写一个对应的服务降级处理类,也就是我们fallback类,这里需要实现Fegin调用接口就可以了
@Component // 将该fallback类交由给Spring管理
public class OrderStatisticFeginClientFallback implements OrderStatisticFeginClient {
// fallback 处理逻辑
@Override
public Integer getTodayFinishOrderNum(Integer id) {
return -1;
}
}
其实这里我们还需要改一下 Fegin调用接口,这里也就是OrderStatisticFeginClient ,需要把接口上面的@RequestMapping("/order/data") 这个注解值放到 @FeignClient注解的path属性中
@FeignClient(name = "spring-cloud-order-service-provider",path = "/order/data",fallback = OrderStatisticFeginClientFallback.class)
//@RequestMapping("/order/data")// 这里你服务提供者接口controller 啥样 可以照着搬过来,当然也可以写到FeignClient注解的path属性上。
public interface OrderStatisticFeginClient {
// 请求路径,FeginClient增加了对Springmvc的支持,所以可以直接将服务提供者接口controller 方法搬过来,然后去掉方法体
@GetMapping("/getTodayFinishOrderNum/{id}")
public Integer getTodayFinishOrderNum(@PathVariable("id") Integer id);
}
这里我们需要修改下Ribbon的配置,不让它重试
# 单独对这个spring-cloud-order-service-provider 服务的调用生效,如果想配置全局生效的话可以不用写这个服务名,
spring-cloud-order-service-provider:
ribbon:
# 这个是连接超时时间
ConnectTimeout: 1000
# 这个是服务处理请求超时时间
ReadTimeout: 5000
# 对所有的操作进行重试工作
OkToRetryOnAllOperations: false
# 当超时的时候,最大重试次数,这个请求重试是在超时服务上试 , 这里是设置了0次,就是不进行重试
MaxAutoRetries: 0
# 如果在调用当前服务重试次数没了,就换个服务
MaxAutoRetriesNextServer: 0
#负载均衡策略
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
重启用户服务,也就是服务调用者服务。
postman发起请求
我们可以看到5秒左右就发生了熔断,执行了咱们fallback方法。这是因为,当我们配置了Fegin超时时间 与Hystrix 超时时间时,熔断超时取的是最小的那个时间。
我们在使用Fegin的时候发起服务调用的时候,可以对请求与响应进行压缩,然后来减少网络通信的性能开销,我们可以通过配置就可以开启对请求与响应的压缩功能,需要我们在配置文件application.yml中添加如下配置:
feign:
compression:
request:
# 开启请求压缩功能
enabled: true
#设置压缩的数据类型,此处也是默认值
mime-types: text/html,application/xml,application/json
# 设置什么时候触发压缩,当大小超过2048的时候
min-request-size: 2048
# 开启响应压缩功能
response:
enabled: true
我们还可以通过配置开启Fegin的日志功能,这样就能够看到一些更细节的请求信息与响应信息。
我们要看到Fegin的日志信息需要2处配置,分别是Fegin自身日志 与 系统log的一个配置,开启Fegin日志功能
开启Fegin自身日志需要我们使用配置类来配置
@Configuration
public class FeginLogConfiguration {
@Bean
public Logger.Level feginLogLevel(){
return Logger.Level.FULL;
}
}
我们来看下Fegin log level 都有哪些
Logger.Level | 解释 |
---|---|
NONE | 表示不显示任何日志,默认 |
BASIC | 基本的日志,能够记录请求方法、URL、响应状态码以及执行时间 适用于生产 |
HEADERS | 在BASIC级别的基础上记录请求和响应的header |
FULL | 全部日志,记录请求和响应的header、body和元数据 适用于开发 |
需要我们在配置文件application.yml中配置log日志
#Feign日志只会对日志级别为debug的做出响应
logging:
level:
com.xuzhaocai.consumer.service.OrderStatisticFeginClient: debug
我们重启服务调用者服务
浏览器发起请求:http://127.0.0.1:8080/user/data/getTodayStatistic/100
查看服务调用者日志,我们就可以看到Fegin调用信息了