一、Spring Cloud OpenFeign介绍
Feign [feɪn] 译文 伪装。Feign是一个轻量级的Http封装工具对象,大大简化了Http请求,它的使用方法 是定义一个接口,然后在上面添加注解。不需要拼接URL、参数等操作。项目主页:GitHub - OpenFeign/feign: Feign makes writing java http clients easier
- 集成Ribbon的负载均衡功能;
- 集成了Hystrix的熔断器功能;
- 支持请求压缩;
- 大大简化了远程调用代码,同时功能还增强了;
- Feign以更优雅的方式编写远程调用代码,并简化了重复代码;
1.1业务分析
按照上图所示,我们就要实现打车用户打车下单,打车下单的时候需要匹配指定司机并更改司机状态,由之 前空闲状态改成接单状态。这时候就涉到 hailtaxi-order服务调用 hailtaxi-driver服务了,此时 如果使用HttpClient工具,操作起来非常麻烦,我们可以使用 SpringCloud OpenFeign实现调用。
1.2OpenFeign应用
使用OpenFeign实现服务之间调用,可以按照如下步骤实现:
- 导入feign依赖;
- 编写feign客户端接口-将请求地址写到该接口上;
- 消费者启动类上加开启feign功能注解;
- 访问测试接口;
1)导入依赖
在 hailtaxi-api 中导入如下依赖:
<!--配置feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2)创建Feign客户端接口
代码如下:
@FeignClient(value = "hailtaxi-driver")//value = "hailtaxi-driver"指定服务的名字
public interface DriverFeign {
/****
* 更新司机信息,该方法和hailtaxi-driver服务中的方法保持一致
*/
@PutMapping(value = "/driver/status/{id}/{status}")
Driver status(@PathVariable(value = "id")String id, @PathVariable(value = "status")Integer status);
}
参数说明:Feign启动的时候会扫描所有带有@FeignClient的注解,最后会通过动态代理,帮我们生成实现类,注解@FeignClient声明Feign的客户端,注解value指明的是服务的名称,接口定义的方法,采用SpringMVC的注解。Feign会根据注解帮我们生成URL地址。
3)Controller调用
修改 hailtaix-order 的下单方法,在下单方法中调用 DriverFeign修改司机状态,代码如下:
/****
* 更新司机信息
*/
@PutMapping(value = "/status/{id}/{status}")
public Driver status(@PathVariable(value = "id")String id,@PathVariable(value = "status")Integer status){
Driver driver = new Driver(id,"张司机(18081)",5.0f,null,status);
System.out.println("司机状态变更(18081):"+driver);
return driver;
}
4)启动OpenFeign
以上的准备工作做完之后,此时我们就要启动OpenFeign,此时我们就要启动类上加上注解,代码如下:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = "com.itheima.driver.feign")
public class DriverApplication {
public static void main(String[] args) {
SpringApplication.run(DriverApplication.class,args);
}
}
1.3数据压缩
用户在网络请求的过程中,如果网络不佳、传输数据过大,会造成体验差的问题,我们需要将传输的数据进行压缩来提升体验。SpringCloud OpenFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。
通过配置开启请求与响应的压缩功能:
server:
port: 18084
spring:
application:
name: hailtaxi-driver
cloud:
#Consul配置
consul:
host: localhost
port: 8500
discovery:
#注册到Consul中的服务名字
service-name: ${spring.application.name}
feign:
compression:
request:
enabled: true # 开启请求压缩
response:
enabled: true # 开启响应压缩
也可以对请求的数据类型,以及触发压缩的大小下限进行设置:
server:
port: 18084
spring:
application:
name: hailtaxi-driver
cloud:
#Consul配置
consul:
host: localhost
port: 8500
discovery:
#注册到Consul中的服务名字
service-name: ${spring.application.name}
feign:
compression:
request:
enabled: true # 开启请求压缩
mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
min-request-size: 2048 # 设置触发压缩的大小下限
#以上数据类型,压缩大小下限均为默认值
response:
enabled: true # 开启响应压缩
1.4OpenFeign日志配置
我们知道可以通过loggin.level.xx=debug来设置日志级别,但是这个对Feign客户端不会生效,@FeignClient注解修饰的客户端在被代理时,都会创建一个新的Feign.Logger实例。我们需要额外通过 配置类的方式指定这个日志的级别才可以。
1)普通日志级别设置
在 hailtaxi-order 的配置文件中设置com.itheima包下的日志级别都为debug :
# com.jokerMqc包下的日志级别都为Debug
logging:
level:
com.jokerMqc: debug
2) Feign日志等级配置
在 hailtaxi-order 启动类 OrderApplication 中创建 Logger.Level ,定义日志级别:
/***
* 日志级别
* @return
*/
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
feign支持4种级别,如下:
- NONE:不记录任何日志,默认值;
- BASIC:仅记录请求的方法,URL以及响应状态码和执行时间;
- HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息;
- FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据;
重启之后,访问打印如下:
二、Spring Cloud Ribbon
2.1什么是ribbon
Ribbon是NetFlix发布的负载均衡器,有助于控制HTTP客户端行为。为Ribbon配置服务提供者地址列表后,Ribbon就可以基于负载均衡算法,自动帮助服务消费者发送请求。
Ribbon默认提供的负载均衡算法:轮询,随机,重试法,加权,当然我们也可以实现自己的负载均衡算法。
有人会有一个疑问,Nginx也可以实现负载均衡,那他跟Ribbon有什么区别,其实Nginx是在服务器端在负载均衡,而Ribbon是发生在客户端的负载均衡。
2.2Ribbon使用
1)业务分析
如上图, 当用户下单调用 hailtaxi-order服务的时候,该服务会调用 hailtaxi-driver ,此时如果是 抢单过程,查询压力也会很大,我们可以为 hailtaxi-driver做集群,做集群只需要把工程复制多分 即可,多个工程如下图:
2)调用测试
此时我们执行 http://localhost:8001/order?token=zhangsan调用,可以发现已经实现负载均衡 了, 18081 和 18084 服务会轮询着调用。
2.3Ribbon算法
上面我们没有做任何操作,只是把服务做成集群就实现了负载均衡,这是因为OpenFeign默认使用了Ribbon的轮询算法,如下图:
我们如果想改变相关算法,可以直接在 application.yml 中配置算法即可。
#修改负载均衡算法,默认是轮询,配置之后变随机
ribbon:
#轮询
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
#随机算法
#NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
#重试算法,该算法先按照轮询的策略获取服务,如果获取服务失败则在指定的时间内会进行重试,获取可用的服务
#NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule
#加权法,会根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越大。刚启动时如果同统计信息不足,则使用轮询的策略,等统计信息足够会切换到自身规则。
#NFLoadBalancerRuleClassName: com.netflix.loadbalancer.ZoneAvoidanceRule
2.4自动负载均衡算法
public class MyRule implements IRule {
@Override
public Server choose(Object o) {
// 这里实现自己的负载均衡算法
return null;
}
@Override
public void setLoadBalancer(ILoadBalancer iLoadBalancer) {
}
@Override
public ILoadBalancer getLoadBalancer() {
return null;
}
}