一、前言
在前面使用Eureka时,我们在微服务之间调用使用的是RestTeplate,使用较为复杂,要拼接字符串。
Feign是声明式的web service客户端,我们只需要编写一个接口就可以通过http请求实现服务的调用。OpenFeign是Feign的扩展,能支持SpringMVC注解,同时他还集成了Ribbon,Hystrix。
二、OpenFeign的使用
1.引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.编写Feign客户端接口
@Component
@FeignClient(value = "product-service")
public interface ProductServiceClient {
@GetMapping("/productservice/sysProduct/product/{productId}")
SysProduct getProductById(@PathVariable Long productId);
@GetMapping("/productservice/sysProduct/product-page")
Page<SysProduct> getProductPage(@RequestParam(required = false, defaultValue = "1") Long current,
@RequestParam(required = false, defaultValue = "2") Long size);
@PostMapping("/productservice/sysProduct/product")
SysProduct addProduct(@RequestBody SysProduct product);
@PutMapping("/productservice/sysProduct/product")
SysProduct updateProduct(@RequestBody SysProduct product);
@DeleteMapping("/productservice/sysProduct/product/{productId}")
ResponseResult<Long> removeProductById(@PathVariable Long productId);
}
这里把product-service项目中的controller中的所有内容复制过来,然后把方法体删掉。
3.启动类上加@EnableFeignClients注解
@EnableFeignClients(basePackages = "com.blb.common.feign")
我将接口写在了共享目录中,路径是com.blb.common.feign
4.调用
@Autowired private ProductServiceClient productServiceClient; @Override public SysOrder getOrderById(Long id) { SysOrder sysOrder = orderMapper.selectById(id); SysProduct product = productServiceClient.getProductById(Long.valueOf(sysOrder.getProductId())); sysOrder.setProduct(product); return sysOrder; }
三、Ribbon
Feign中默认整合了Ribbon实现负载均衡
1.修改配置文件中
# Ribbon负载均衡策略选择 ribbon前是服务名 RoundRobinRule是简单的轮询 product-service.ribbon.NFLoadBalancerRuleClassName = com.netflix.loadbalancer.RoundRobinRule
此时以及开启了负载均衡
以下为测试负载均衡是否实现
2.配置多个product-service服务
复制配置文件,修改端口号
@Value("${server.port}") private Integer port; @GetMapping("/product/{productId}") public SysProduct getProductById(@PathVariable Long productId){ SysProduct product = productService.getById(productId); product.setName(product.getName() + ",from: port=" + port); return product; }
效果如下
四、Hystirx
Feign同样默认整合了Hystirx熔断器机制
此前使用Hystirx是在控制器中编写方法。Feign可以单独定义类,编写降级方法
1.定义降级处理类,实现对应的FeignClient接口
实现的所有方法都为降级方法
/**
* 降级处理类
*/
@Component
public class ProductServiceFallback implements ProductServiceClient {
@Override
public SysProduct getProductById(Long productId) {
return new SysProduct(0, "兜底数据", 0, "");
}
@Override
public Page<SysProduct> getProductPage(Long current, Long size) {
return new Page<>();
}
@Override
public SysProduct addProduct(SysProduct product) {
return new SysProduct(0, "兜底数据", 0, "");
}
@Override
public SysProduct updateProduct(SysProduct product) {
return new SysProduct(0, "兜底数据", 0, "");
}
@Override
public ResponseResult<Long> removeProductById(Long productId) {
return ResponseResult.ok(0); }
}
2.在Feign注解中添加配置
@FeignClient(value = "product-service", fallback = ProductServiceFallback.class)
3.在配置文件中启用Hystrix特性
# 启动Feign的Hystrix特性 feign.hystrix.enabled=true
4.此外,若Feign接口,降级类以及服务提供者不再同一个项目中需要添加包的扫描
@SpringBootApplication(scanBasePackages = {"com.blb.orderservice","com.blb.common"})
五、Feign优化
1.连接池优化
Feign是基于HTTP协议,HTTP协议基于TCP协议,TCP具有三次握手四次挥手机制,频繁的创建连接比较消耗系统的资源和时间,降低系统的吞吐量。
使用连接池可以减少网络连接的创建,提高连接的使用效率,提高系统吞吐量。
Feign默认使用JDK自带的HttpURLConnection,没有连接池。
可以使用HttpClient或OkHttp
1)导入依赖
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
2.)修改配置文件
# 使用连接池 feign-httpclient feign.httpclient.enable=true
2.请求压缩优化
Feign可以对网络数据进行GZIP压缩,减少网络流量,提高速度
修改配置文件
#启动请求压缩
feign.compression.request.enabled=true
#启动响应压缩
feign.compression.response.enabled=true
#设置请求压缩的多媒体类型
feign.compression.request.mime-types=text/html,application/xml,application/json
#设置请求压缩的下限 (默认2048)
feign.compression.request.min-request-size=1024
3.使用日志对连接过程进行监控
1.)修改配置文件
# logging.level.包名.FeignClient接口名=DEBUG
# 开启网络调用的日志 logging.level.com.blb.commoncloud.feign.ProductServiceClient=DEBUG
2)定义配置类,配置日志
/** * feign日志配置 */ @Configuration public class FeignLoggerConfig { /** * 返回日志类型,NONE没有日志,BASIC基本信息(请求方法,URL,响应代码等),HEADERS(头部信息),FULL(基本+头部) * @return */ @Bean public Logger.Level level(){ return Logger.Level.FULL; } }
4.超时优化
Ribbon是具有重试机制的,就是连接失败后进行重连,问题是:Hystrix的超时时间默认是小于Ribbon的超时,Hystrix会提前熔断,Ribbon无法进行重试
Hystrix的超时要大于Ribbon的超时
修改配置文件
# hystrix的超时
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000
# ribbon的超时
ribbon.ConnectionTimeout=1000
ribbon.ReadTimeout=3000