Spring Cloud 常见的集成方式是使用Feign+Ribbon技术来完成服务间远程调用及负载均衡的,如下图
采用Feign+Ribbon的整合方式,是由Feign完成远程调用的整个流程。而Feign集成了Ribbon,Feign使用Ribbon
完成调用实例的负载均衡。
在SpringCloud服务协议流程中,ServiceA通过负载均衡调用ServiceB,下边来了解一下负载均衡:
负载均衡就是将用户请求(流量)通过一定的策略,分摊在多个服务实例上执行,它是系统处理高并发、缓解网络
压力和进行服务端扩容的重要手段之一。它分为服务端负载均衡和客户端负载均衡。
服务器端负载均衡:
客户端负载均衡:
Feign 的英文表意为“假装,伪装,变形”, 是一个http请求调用的轻量级框架,是以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。Feign通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求,这种请求相对而言比较直观。
Feign被广泛应用在Spring Cloud 的解决方案中,是学习基于Spring Cloud 微服务架构不可或缺的重要组件。
**封装了Http调用流程,更符合面向接口化的编程习惯。**类似Dubbo服务调用。
项目主页:https://github.com/OpenFeign/feign
使用Feign替代RestTemplate发送Rest请求。使之更符合面向接口化的编程习惯。
实现步骤:
实现过程:
在consumer-service中添加spring-cloud-starter-openfeign
依赖
<!--配置feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
在consumer-service中编写Feign客户端接口类ConsumerService
@FeignClient(value = "provider-service")
public interface ConsumerService {
//String url = String.format("http://provider-service/user/findUserById/%s",id);
@RequestMapping("/user/findUserById/{id}")
User findUserById(@PathVariable("id") Integer id);
}
编写ConsumerFeignController,使用ConsumerService访问
@Autowired注入ConsumerService
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private ConsumerService consumerService;
@GetMapping("/findUserById/{id}")
public User findUserById(@PathVariable Integer id){
return consumerService.findUserById(id);
}
}
在ConsumerApplication启动类上,添加@EnableFeignClients
注解,开启Feign功能
@SpringBootApplication
@EnableFeignClients //开启feign
@EnableDiscoveryClient
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
访问接口http://localhost:8081/consumer/findUserById/1,正常获取结果:
Feign帮我们做了哪些事儿:
Feign本身集成了Ribbon,因此不需要额外引入依赖。
Ribbon是一个客户端负载均衡器,它的责任是从一组实例列表中挑选合适的实例,如何挑选?取决于负载均衡策
略 。
Ribbon核心组件IRule是负载均衡策略接口,它有如下实现,大家仅做了解:
可通过下面方式在spring boot 配置文件中修改默认的负载均衡策略:
account‐service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
account-service
是调用的服务的名称,后面的组成部分是固定的。
Feign本身也集成Hystrix熔断器,starter内查看。
服务降级方法实现步骤:
实现过程:
在配置文件application.yml中开启feign熔断器支持:默认关闭
feign:
hystrix:
enabled: true # 开启Feign的熔断功能
定义一个类ConsumerServiceImpl,实现刚才编写的ConsumerService,作为FallBack的处理类
@Component
public class ConsumerServiceImpl implements ConsumerService {
//熔断方法
@Override
public User findUserById(Integer id) {
User user = new User();
user.setId(id);
user.setNote("网络异常,请稍后再试...");
return user;
}
}
在@FeignClient注解中,指定FallBack处理类。。
@FeignClient(value = "provider-service",fallback = ConsumerServiceImpl.class)
public interface ConsumerService {
//String url = String.format("http://provider-service/user/findUserById/%s",id);
@RequestMapping("/user/findUserById/{id}")
User findUserById(@PathVariable("id") Integer id);
}
重启测试:关闭provider-service服务,然后在页面访问;http://localhost:8081/consumer/findUserById/1
SpringCloudFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。
通过配置开启请求与响应的压缩功能:
feign:
compression:
request:
enabled: true # 开启请求压缩
response:
enabled: true # 开启响应压缩
也可以对请求的数据类型,以及触发压缩的大小下限进行设置
# Feign配置
feign:
compression:
request:
enabled: true # 开启请求压缩
mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
min-request-size: 2048 # 设置触发压缩的大小下限
#以上数据类型,压缩大小下限均为默认值
在发送和接收请求的时候,Feign定义了日志的输出定义了四个等级:这里我们配置测试一下。
级别 | 说明 |
---|---|
NONE | 不做任何记录 |
BASIC | 只记录输出Http 方法名称、请求URL、返回状态码和执行时间 |
HEADERS | 记录输出Http 方法名称、请求URL、返回状态码和执行时间 和 Header 信息 |
FULL | 记录Request 和Response的Header,Body和一些请求元数据 |
实现步骤:
实现过程:
在consumer-service的配置文件中设置com.itheima包下的日志级别都为debug
# com.itheima 包下的日志级别都为Debug
logging:
level:
com.itheima: debug
在consumer-service编写配置类,定义日志级别
@Configuration
public class FeignLogLevleConfig {
//采用full打印日志
@Bean
public Logger.Level configLog(){
return Logger.Level.FULL;
}
}
在consumer-service的ConsumerService中指定配置类
@FeignClient(value = "provider-service",
fallback = ConsumerServiceImpl.class,
configuration = FeignLogLevleConfig.class)
public interface ConsumerService {
@RequestMapping("/user/findUserById/{id}")
User findUserById(@PathVariable("id") Integer id);
}
重启项目,即可看到每次访问的日志