今日学习目标:
Feign、Ribbon、Hystrix
✅创作者:林在闪闪发光
⏰预计时间:30分钟
个人主页:林在闪闪发光的个人主页林在闪闪发光的个人社区,欢迎你的加入: 林在闪闪发光的社区
Feign 使得用 Java 写 Http 客户端更加容易,这是 Feign 的核心能力!!!
Feign 将其抽象为一套通用逻辑,类似于写普通方法调用一样,Feign 做一层代理,封装这些冗余操作。
feign 大致提供了这些核心能力:
Feign是一款Java语言编写的HttpClient绑定器,在Spring Cloud微服务中用于实现微服务之间的声明式调用。Feign 可以定义请求到其他服务的接口,用于微服务间的调用,不用自己再写http请求,在客户端实现,调用此接口就像远程调用其他服务一样,当请求出错时可以调用接口的实现类来返回
Feign是一个声明式的web service客户端,它使得编写web service客户端更为容易。创建接口,为接口添加注解,即可使用Feign。Feign可以使用Feign注解或者JAX-RS注解,还支持热插拔的编码器和解码器。Spring Cloud为Feign添加了Spring MVC的注解支持,并整合了Ribbon和Eureka来为使用Feign时提供负载均衡。
org.springframework.cloud
spring-cloud-starter-openfeign
org.apache.httpcomponents
httpclient
io.github.openfeign
feign-httpclient
启动类增加 注解
@EnableFeignClients
Feign内置了Ribbon
//创建服务提供者
@RestController
@RequestMapping("/provider")
public class ProviderController {
@Autowired
private UserService userService;
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable Integer id){
return userService.getUserById(id);
}
}
/**
* @FeignClient 一般采用服务名进行命名
* name:指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现
* url: url一般用于调试,可以手动指定@FeignClient调用的地址
*
* @RequestMapping 主要用于feign框架拼接传递url,弥补了Ribbon的url需要手动拼接的缺陷
* @PathVariable("id") 当路径为restful风格时路径传参方式
* @RequestParam("id") 当路径为?id=250 时传参方式
* @RequestBody User user 当路径为对象时采用的传参方式,(集合、数组等都属于对象)
*/
@FeignClient("feign-provider")
@RequestMapping("/provider")
public interface UserFeign {
@RequestMapping("/getUserById/{id}")
User getUserById(@PathVariable("id") Integer id);
@RequestMapping("/deleteUserById")
User deleteUserById(@RequestParam("id") Integer id);//?形式拼接参数,?id=250
@RequestMapping("/addUser")
User addUser(@RequestBody User user);//pojo--->json
}
//服务消费者
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private UserFeign userFeign;
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable Integer id){
return userFeign.getUserById(id);
}
}
server:
port: 80
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.209.129:8848
application:
name: feign-consumer
feign源码的github地址:
GitHub - OpenFeign/feign: Feign makes writing java http clients easier
Ribbon 作为负载均衡,在客户端实现,服务段可以启动两个端口不同但servername一样的服务
Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。简单地说,Ribbon是一个客户端负载均衡器。
Ribbon工作时分为两步:第一步先选择 Eureka Server, 它优先选择在同一个Zone且负载较少的Server;第二步再根据用户指定的策略,在从Server取到的服务注册列表中选择一个地址。其中Ribbon提供了多种策略,例如轮询、随机、根据响应时间加权等。
(如果不使用ribbon的方式调用,直接使用feign即可;可不引用)
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
调用的时候直接使用服务名
String url="http://EUREKA-PROVIDE/goods/findOne/"+id;
Goods goods = restTemplate.getForObject(url, Goods.class);
在provider中加上几行代码,显示调用的端口号
@Autowired
private GoodsService goodsService;
@Value("${server.port}")
private Integer port;
@RequestMapping("/findOne/{id}")
public Goods findOne(@PathVariable Integer id){
Goods goods = goodsService.findOne(id);
goods.setTitle(goods.getTitle()+":"+port);//将端口号,设置到了 商品标题上
return goods;
}
Ribbon负载均衡策略:
随机 :RandomRule
轮询 :RoundRobinRule(默认的负载均衡策略)
最小并发:BestAvailableRule(服务A-1,服务A-2,服务A-3,这三个服务中谁最闲一般认为是性能高)
过滤:AvailabilityFilteringRule(坏的服务过滤掉)
响应时间:WeightedResponseTimeRule(发送一个数据包到三个服务中,看谁最先响应,谁快就调用谁)
轮询重试:RetryRule(默认轮询10次,如果节点出现问题,会去找第二个,如果轮询到10次都挂了那就响应失败)
性能可用性:ZoneAvoidanceRule(综合考虑性能和可用性,看谁分数高就用谁)
hystrix 专注于解决分布式系统延迟和容错问题。换句话说,hystrix 主要解决服务通信间的网络延时、异常等,提供降级和熔断等能力。
还不够通俗?当你在服务 A 调用服务 B 的接口时,可能出现超时、异常的情况,很有可能是服务 B 压力过大,已不堪重负。这时,服务 A 该如何做?
我们可以考虑一些策略,比如,请求失败了,我们返回默认结果;失败率超过多少多少,直接短暂停用接口调用。
Hystrix 便是致力于解决这类问题,实现以上的各种处理策略,熔断、降级等。
遗憾的是,官方已经声明不在维护
Hystrix 在 Netflix 稳定运行多年,足够稳健,我们可以放心在生产环境使用。
org.springframework.cloud
spring-cloud-starter-hystrix
启动类开启熔断
@EnableCircuitBreaker
定义@HystrixCommand
@RestController
public class RemoteCallerController {
@Autowired
private IUserService iUserService;
@GetMapping("/user/sayHi/{name}")
@HystrixCommand(fallbackMethod="sayHiFallback")
public CommonRsp sayHi(@PathVariable("name") String name) throws Exception {
return iUserService.sayHi(name);
}
public CommonRsp sayHiFallback(@PathVariable("name") String name) throws Exception {
return CommonRspUtils.buildSuccessRsp("接口失败");
}
}
如果微服务项目加上了spring-cloud-starter-netflix-hystrix依赖,那么,feign会通过代理模式, 自动将所有的方法用 hystrix 进行包装。
在Spring Cloud微服务体系下,微服务之间的互相调用可以通过Feign进行声明式调用,在这个服务调用过程中Feign会通过Ribbon从服务注册中心获取目标微服务的服务器地址列表,之后在网络请求的过程中Ribbon就会将请求以负载均衡的方式打到微服务的不同实例上,从而实现Spring Cloud微服务架构中最为关键的功能即服务发现及客户端负载均衡调用。
另一方面微服务在互相调用的过程中,为了防止某个微服务的故障消耗掉整个系统所有微服务的连接资源,所以在实施微服务调用的过程中我们会要求在调用方实施针对被调用微服务的熔断逻辑。而要实现这个逻辑场景在Spring Cloud微服务框架下我们是通过Hystrix这个框架来实现的。
调用方会针对被调用微服务设置调用超时时间,一旦超时就会进入熔断逻辑,而这个故障指标信息也会返回给Hystrix组件,Hystrix组件会根据熔断情况判断被调微服务的故障情况从而打开熔断器,之后所有针对该微服务的请求就会直接进入熔断逻辑,直到被调微服务故障恢复,Hystrix断路器关闭为止。
三者之间的关系图,大致如下:
feign:
hystrix:
enabled: true
# feign 的 http 客户端支持 3 种框架;
#HttpURLConnection、httpclient、okhttp;默认是HttpURLConnection(并不支持连接池)。
httpclient:
enabled: true # 开启 httpclient
client:
config:
default:
#默认日志记录NONE【性能最佳,适用于生产】:不记录任何日志(默认值)。
#BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间。
#HEADERS:记录BASIC级别的基础上,记录请求和响应的header。
#FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数据。
loggerLevel: HEADERS
#连接超时时间
connectTimeout: 5000
#读取超时时间
readTimeout: 5000
hystrix:
propagate:
request-attribute:
enabled: true
command:
#全局默认配置
default:
#线程隔离相关
execution:
timeout:
#是否给方法执行设置超时时间,默认为true。一般我们不要改。
enabled: true
isolation:
#配置请求隔离的方式,这里是默认的线程池方式。还有一种信号量的方式 THREAD semaphore,使用比较少。
strategy: THREAD
thread:
#方式执行的超时时间,默认为1000毫秒,在实际场景中需要根据情况设置
timeoutInMilliseconds: 10000
#发生超时时是否中断方法的执行,默认值为true。不要改。
interruptOnTimeout: true
#是否在方法执行被取消时中断方法,默认值为false。没有实际意义,默认就好!
interruptOnCancel: false
circuitBreaker: #熔断器相关配置
enabled: true #是否启动熔断器,默认为true,false表示不要引入Hystrix。
requestVolumeThreshold: 20 #启用熔断器功能窗口时间内的最小请求数,假设我们设置的窗口时间为10秒,
sleepWindowInMilliseconds: 5000 #所以此配置的作用是指定熔断器打开后多长时间内允许一次请求尝试执行,官方默认配置为5秒。
errorThresholdPercentage: 50 #窗口时间内超过50%的请求失败后就会打开熔断器将后续请求快速失败掉,默认配置为50
ribbon:
eager-load:
enabled: true
#说明:同一台实例的最大自动重试次数,默认为1次,不包括首次
MaxAutoRetries: 1
#说明:要重试的下一个实例的最大数量,默认为1,不包括第一次被调用的实例
MaxAutoRetriesNextServer: 1
#说明:是否所有的操作都重试,默认为true
OkToRetryOnAllOperations: true
#说明:从注册中心刷新服务器列表信息的时间间隔,默认为2000毫秒,即2秒
ServerListRefreshInterval: 2000
#说明:使用Apache HttpClient连接超时时间,单位为毫秒
ConnectTimeout: 3000
#说明:使用Apache HttpClient读取的超时时间,单位为毫秒
ReadTimeout: 3000
希望对未知的你们有所帮助
❤林林在闪闪发光