SpringCloud之Hystrix环境搭建
Posted 王大军
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud之Hystrix环境搭建相关的知识,希望对你有一定的参考价值。
前言
Hystrix是一个用于处理分布式系统的延迟和容错和开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix能保证在一个依赖出现问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性;
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障 监控(类似熔断保险丝),向调用方返回一个符合预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
服务熔断
熔断机制是应对雪崩效应的一种微服务 链路保护机制;
当扇出链路的某个服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回“错误”的响应信息,当检测到该节点微服务调用响应正常后 恢复调用链路,在springcloud框架里熔断机制通过Hystrix实现,Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒20次调用失败就会启动熔断机制,熔断机制的注解是@HystrixCommand
服务降级
整体资源快不够用了,忍痛将某些服务先关掉,待度过难关,在开启回来。
所谓降级,就是一般是从整体符合考虑,就是当某个服务熔断之后,服务器将不再被调用,此刻客户端可以自己准备一个本地的fallback回调,返回一个缺省值,这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强。
服务熔断环境搭建
1. 创建springcloud-provider-dept-hystrix-8001服务提供者
① 修改pom依赖,和springcloud-provider-dept-8001中的pom相同,复制过来 然后添加Hystrix依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> <version>1.4.6.RELEASE</version> </dependency>
② 编写application.ym配置文件
server: port: 8001 # 当前微服务的端口 mybatis: config-location: classpath:mybatis/mybatis-config.xml # mybatis配置文件所在路径 type-aliases-package: com.common.springcloud.entity # 所有饿entity实体类所在包 mapper-locations: - classpath:mybatis/mapper/*.xml # mapper映射文件 spring: application: name: springcloud-provider-dept-hystrix # 对外暴露的微服务的名字(很重要) datasource: type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型 driver-class-name: org.gjt.mm.mysql.Driver # mysql驱动包 url: jdbc:mysql://localhost:3306/db01?useUnicode=true&serverTimezone=GMT%2B8&characterEncoding=UTF-8&useSSL=false # 数据库名称 username: root password: 123456 druid: # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个, #注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串 test-on-borrow: false # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除. #注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串 test-while-idle: true # 指明是否在归还到池中前进行检验,注意: 设置为true后如果要生效, #validationQuery参数必须设置为非空字符串 test-on-return: false # SQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前. #如果指定,则查询必须是一个SQL SELECT并且必须返回至少一行记录 validation-query: select 1 eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://eureka1:7001/eureka/,http://eureka2:7002/eureka/,http://eureka3:7003/eureka/ #去注册中心的地址 #defaultZone:7001,7002,7003 去注册中心的地址 instance: instance-id: springcloud-dept-hystrix8001 #自定义hystrix相关的服务名称信息 prefer-ip-address: true #访问路径可以显示ip地址 info: app.name: wj-springcloud company.name: www.wj.com build.artifactId: $project.artifactId$ build.version: $project.version$
③ 在相关类添加注解
Controller类
package com.yt.springcloud.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import com.yt.springcloud.entity.Dept; import com.yt.springcloud.service.impl.DeptService; @RestController//整合了responceBody+Controller public class DeptController { @Autowired private DeptService service = null; @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET) //一旦调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法 @HystrixCommand(fallbackMethod = "processHystrix_Get")//发生异常的时候,会调用这个fallbackmethod方法,去处理 public Dept get(@PathVariable("id") Long id){ Dept dept = this.service.get(id); if (null == dept) { throw new RuntimeException("该ID:" + id + "没有没有对应的信息"); } return dept; } /** * 发生异常的时候,会调用这个方法来处理,还是返回一个dept对象,但是里面的信息是我们自定义的
* 下面的链路赋值形式:new ObjectTest().setXX().setXX().....; 需要导入lombok依赖即可 * @param id * @return */ public Dept processHystrix_Get(@PathVariable("id") Long id){ return new Dept().setDeptno(id).setDname("该ID:" + id + "没有没有对应的信息,null--@HystrixCommand") .setDb_source("no this database in MySQL"); } }
ApplicationBoot启动类
package com.yt.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient //本服务启动后会自动注册进eureka服务中 @EnableDiscoveryClient //服务发现 @EnableCircuitBreaker//对hystrixR熔断机制的支持!!! public class DeptProvider8001_Hystrix_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_Hystrix_App.class, args); } }
测试
启动Eureka服务注册服务,如果搭建了集群,全部启动也可。
启动Hystrix服务提供者服务
启动服务消费者
打开注册Eureka页面:http://localhost:7001/ #打开自己设置URL即可
进行接口调用
测试id为1,数据是OK的
当的id不存在的时候,会进入容错的方法,返回刚刚设置的返回值
服务降级环境搭建
服务降级处理是在客户端完成的,与服务端没有关系
修改springcloud-api工程,根据已经有的DeptClientService接口新建一个实现了FallbackFactory接口的类DeptClientServiceFallbackFactory
package com.yt.springcloud.service; import java.util.List; import org.springframework.stereotype.Component; import com.yt.springcloud.entity.Dept; import feign.hystrix.FallbackFactory; @Component public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> { @Override public DeptClientService create(Throwable throwable) { return new DeptClientService() { @Override public Dept get(long id) { return new Dept().setDeptno(id).setDname("该ID:" + id + "没有没有对应的信息,Consumer客户端提供的降级信息,此刻服务Provider已经关闭") .setDb_source("no this database in MySQL"); } @Override public List<Dept> list() { return null; } @Override public boolean add(Dept dept) { return false; } }; } }
修改springcloud-api工程,DeptClientService接口在注解@FeignClient
import com.common.springcloud.pojo.Dept; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import java.util.List; //@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")//针对于更细粒化的控制,针对哪一个微服务进行面向接口的feign的 @FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT", fallback = DeptClientServiceFallbackFactory.class) public interface DeptClientService { @GetMapping("/dept/get/{id}") public Dept queryId(@PathVariable("id") Long id); @GetMapping("/dept/list") public List<Dept> queryAll(); @PostMapping("/dept/list") public boolean addDept(Dept dept); }
修改springcloud-consumer-dept-feign工程的application.yml配置文件
测试
1. 启动3个Eureka
2. 微服务springcloud-provider-dept-8001启动
3. springcloud-consumer-dept-feign启动
4. 正常访问测试: http://localhost/consumer/dept/get/1
5. 故意关闭微服务springcloud-provider-dept-8001
6. 客户端(消费者)自己调用提示
此时服务端provider已经down了,但是我们做了服务降级处理,让客户端不可用时也会获得提示信息而不会挂起耗死服务器。
可以看做是服务提供者的一个应急策略,返回服务坏掉的信息。
以上是关于SpringCloud之Hystrix环境搭建的主要内容,如果未能解决你的问题,请参考以下文章
5.springcloud微服务架构搭建 之 《springboot集成Hystrix》
微服务架构整理-(十SpringCloud实战之Hystrix [3])
微服务架构整理-(十SpringCloud实战之Hystrix [3])
微服务架构整理-(十SpringCloud实战之Hystrix [3])
Java之 Spring Cloud 微服务搭建 Hystrix (第二个阶段)SpringBoot项目实现商品服务器端是调用