Feign声明式服务调用
Feign概述
• Feign 是一个声明式的 REST 客户端,它用了基于接口的注解方式,很方便实现客户端配置。
• Feign 最初由 Netflix 公司提供,但不支持SpringMVC注解,后由SpringCloud 对其封装,支持了SpringMVC注 解,让使用者更易于接受。
- Feign自动集成Ribbon,且默认开启相关功能
- Feign自动集成Hystrix,但默认关闭,需要手动开启
Feign 快速入门
- 在消费端引入 open-feign 依赖
- 编写Feign调用接口
- 在启动类 添加 @EnableFeignClients 注解,开启Feign功能
- 测试调用
Feign依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
Feign调用接口:
package com.itheima.consumer.feign;import com.itheima.consumer.FeignLogConfig;import com.itheima.consumer.domain.Goods;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;/**
* feign声明式接口,发起远程调用
* String url = "http://FEIGN-PROVIDER/goods/findOne/"+id;
* Goods goods = restTemplate.getForObject(url, Goods.class);
*
* 1.定义接口
* 2.接口上添加注解,@FeignClient,设置属性为 服务提供者的 应用名称,日志级别配置类
* 3.编写调用接口,接口的声明规则和提供方接口保持一致
* 4.注入该接口,调用接口方法完成远程调用
*/@FeignClient(value="FEIGN-PROVIDER",configuration= FeignLogConfig.class)publicinterfaceGoodsFeignClient{@GetMapping("/goods/findOne/{id}")public GoodsfindGoodsById(@PathVariable("id")int id);}
package com.itheima.consumer.controller;import com.itheima.consumer.domain.Goods;import com.itheima.consumer.feign.GoodsFeignClient;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;@RestController@RequestMapping("/order")publicclassOrderController{@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate GoodsFeignClient goodsFeignClient;@GetMapping("/goods/{id}")public GoodsfindGoodsById(@PathVariable("id")int id){
Goods goods= goodsFeignClient.findGoodsById(id);return goods;}}
启动类 开启Feign功能
package com.itheima.consumer;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;import org.springframework.cloud.openfeign.EnableFeignClients;@EnableDiscoveryClient// 激活DiscoveryClient@EnableEurekaClient@SpringBootApplication@EnableFeignClients//开启Feign功能publicclassConsumerApp{publicstaticvoidmain(String[] args){
SpringApplication.run(ConsumerApp.class,args);}}
Feign - 超时设置
服务调用方配置
• Feign 底层依赖于 Ribbon 实现负载均衡和远程调用。
• Ribbon默认1秒超时。
• 超时配置:
Feign - 日志记录
开启SpringBoot框架的debug日志
- 开启全部
# 设置当前的日志级别 debug,feign只支持记录debug级别的日志logging:level:root: debug
- 开启部分
logging:level:com.itheima: debug
服务调用方配置
• Feign 只能记录 debug 级别的日志信息。
• 定义Feign日志级别Bean
服务调用方根包下定义日志级别
package com.itheima.consumer;import feign.Logger;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@ConfigurationpublicclassFeignLogConfig{/**
* NONE:不记录
* BASIC:记录基本的请求行,响应状态码数据
* HEADERS:记录基本的请求行,响应状态码,记录响应头信息
* FULL:记录完整的请求 响应数据
* @return
*/@Beanpublic Logger.Leveldebug(){return Logger.Level.FULL;}}
• 启用该Bean:
@FeignClient(configuration = XxxConfig.class)
package com.itheima.consumer.feign;import com.itheima.consumer.FeignLogConfig;import com.itheima.consumer.domain.Goods;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;/**
* feign声明式接口,发起远程调用
* String url = "http://FEIGN-PROVIDER/goods/findOne/"+id;
* Goods goods = restTemplate.getForObject(url, Goods.class);
*
* 1.定义接口
* 2.接口上添加注解,@FeignClient,设置属性为 服务提供者的 应用名称,日志级别配置类
* 3.编写调用接口,接口的声明规则和提供方接口保持一致
* 4.注入该接口,调用接口方法完成远程调用
*/@FeignClient(value="FEIGN-PROVIDER",configuration= FeignLogConfig.class)publicinterfaceGoodsFeignClient{@GetMapping("/goods/findOne/{id}")public GoodsfindGoodsById(@PathVariable("id")int id);}
Hystrix 熔断器
Hystrix 概述
• Hystix 是 Netflix 开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败(雪崩)。
Hystix 主要功能
- 隔离:用于隔离不同调用链之间相互不受影响
1.线程池隔离
2.信号量隔离 - 降级:封装友好的错误提示并返回
1.异常
2.超时 - 熔断:当请求错误率较高时,自动降级熔断
- 限流:合理分配每个调用的并发请求数量
Hystrix 降级
• Hystix 降级:当服务发生异常或调用超时,返回默认数据
Hystrix 降级 - 服务提供方
- 在服务提供方,引入 hystrix 依赖
- 定义降级方法
- 使用 @HystrixCommand 注解配置降级方法
- 在启动类上开启Hystrix功能:@EnableCircuitBreaker
package com.itheima.provider.controller;import com.itheima.provider.domain.Goods;import com.itheima.provider.service.GoodsService;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.Date;/**
* Goods Controller 服务提供方
*/@RestController@RequestMapping("/goods")publicclassGoodsController{@Autowiredprivate GoodsService goodsService;@Value("${server.port}")privateint port;/**
* 降级
* 1.出现异常
* 2.服务器调用超时
* @param id
* @return
*/@GetMapping("/findOne/{id}")//指定降级后调用的方法名称@HystrixCommand(fallbackMethod="findOne_fallback",commandProperties={//设置hystrix的超时时间,默认1秒@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")})public GoodsfindOne(@PathVariable("id")int id){int i=1/0;try{
Thread.sleep(2000);}catch(InterruptedException e){
e.printStackTrace();}
Goods goods= goodsService.findOne(id);
goods.setTitle(goods.getTitle()+":"+ port);//将端口号,设置到了 商品标题上return goods;}/**
* 定义降级方法:
* 返回值,参数和原方法一致
*/public GoodsfindOne_fallback(int id){
Goods goods=newGoods();
goods.setTitle("降级了.....");return goods;}}
Hystrix 降级 - 服务消费方
- feign 组件已经集成了hystrix 组件。
- 定义feign 调用接口实现类,复写方法,即 降级方法
- 在 @FeignClient 注解中使用 fallback 属性设置降级处理类。
- 配置开启 feign.hystrix.enabled = true
package com.itheima.consumer.feign;import com.itheima.consumer.domain.Goods;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;@FeignClient(value="HYSTRIX-PROVIDER",fallback= GoodsFeignClientFallback.class)publicinterfaceGoodsFeignClient{@GetMapping("/goods/findOne/{id}")public GoodsfindGoodsById(@PathVariable("id")int id);}
package com.itheima.consumer.feign;import com.itheima.consumer.domain.Goods;import org.springframework.stereotype.Component;/**
* feign的客户端降级处理类
* 1.定义类:实现feign客户端接口
* 2.使用@Component注解将该类的Bean加入到Spring中
*/@ComponentpublicclassGoodsFeignClientFallbackimplementsGoodsFeignClient{@Overridepublic GoodsfindGoodsById(int id){
Goods goods=newGoods();
goods.setTitle("又降级了...");return goods;}}
# 开启feign对hystrix的支持feign:hystrix:enabled:true
Hystrix 熔断
• Hystrix 熔断机制,用于监控微服务调用情况,当失 败的情况达到预定的阈值(5秒失败20次),会打开 断路器,拒绝所有请求,直到服务恢复正常为止。
• circuitBreaker.sleepWindowInMilliseconds:监控时间
• circuitBreaker.requestVolumeThreshold:失败次数
• circuitBreaker.errorThresholdPercentage:失败率
Gateway 网关
网关概述
Gateway 网关快速入门
- 搭建网关模块
- 引入依赖:starter-gateway
- 编写启动类
- 编写配置文件
- 启动测试
依赖:
<!--引入gateway网关--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>
配置文件:
server:port:80spring:application:name: api-gateway-servercloud:# 网关配置gateway:# 路由配置:转发规则routes:#集合#id:唯一标识,默认是一个uuid#uri:转发路径#predicates:条件,用于请求网关路径的匹配规则-id: gateway-provider# uri: http://localhost:8001/uri: lb://GATEWAY-PROVIDERpredicates:- Path=/goods/**filters:- AddRequestParameter=username,zhangsan-id: gateway-consumer# uri: http://localhost:9000/uri: lb://GATEWAY-CONSUMERpredicates:- Path=/order/**discovery:locator:enabled:true# 设置为true,请求路径前可以加微服务名称lower-case-service-id:true# 允许小写eureka:client:service-url:defealtZone: http://localhost:8761/eureka
Gateway 网关路由配置
uri:
静态路由:http://locathost:8080/
动态路由:lb://服务名称
Gataway 过滤器
Gateway 过滤器 – 局部过滤器
Gateway 过滤器 – 全局过滤器
自定义全局过滤器
package com.itheima.gateway.filter;import org.springframework.cloud.gateway.filter.GatewayFilterChain;import org.springframework.cloud.gateway.filter.GlobalFilter;import org.springframework.core.Ordered;import org.springframework.stereotype.Component;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono;@ComponentpublicclassMyFilterimplementsGlobalFilter, Ordered{@Overridepublic Mono<Void>filter(ServerWebExchange exchange, GatewayFilterChain chain){
System.out.println("自定义全局过滤器执行了...");return chain.filter(exchange);//放行}/**
* 过滤器排序
* @return 数值越小,越先执行
*/@OverridepublicintgetOrder(){return0;}}