9.Hystrix实践篇

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6


1.业务降级(在film服务工程中修改)
(1).引入依赖

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

(2).controller层开发
在FilmController类中新增获取电影列表降级方法findFilmListFallback,并在findFilmList方法上添加@HystrixCommand注解,具体代码如下。

@Slf4j
@RestController
@RequestMapping("/films")
public class FilmController {
//获取电影列表降级方法
public ServerResponse findFilmListFallback(@RequestBody BasePageVO basePageVO) throws CommonServiceException {
return ServerResponse.createByErrorCodeMessage(500, "请求处理降级返回");
}

//获取电影列表
@HystrixCommand(fallbackMethod = "findFilmListFallback", commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50")
}, threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "10"),
@HystrixProperty(name = "keepAliveTimeMinutes", value = "1000"),
@HystrixProperty(name = "maxQueueSize", value = "10"),
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "8"),
@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "12"),
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "1500")
})
@RequestMapping(value = "/findFilmList", method = RequestMethod.POST)
public ServerResponse findFilmList(@RequestBody BasePageVO basePageVO) throws CommonServiceException {
//检查入参
basePageVO.checkParam();
if (basePageVO.getPageSize() > 1000) {
//业务执行出现异常,触发fallback
throw new CommonServiceException(500, "pageSIze太大");
}

//调用逻辑层,获取返回参数
IPage<Film> results = filmService.findFilmList(basePageVO.getCurrentPage(), basePageVO.getPageSize());

return ServerResponse.createBySuccess(PageUtil.getPageResult(results));
}
}

(3).启动项目
在启动类MoviesFilmApplication上新增注解@EnableHystrix,然后启动项目。

@MapperScan(basePackages = {"com.steven.movies.film.dao"})
@EnableHystrix
@EnableDiscoveryClient
@SpringBootApplication
public class MoviesFilmApplication {

public static void main(String[] args) {
SpringApplication.run(MoviesFilmApplication.class, args);
}

}

(4).测试

启动项目,然后在postman中请求“localhost:8080/movies/film-api/films/findFilmList”,可以查询到相应的信息,测试结果如下图所示。

9.Hystrix实践篇_hystrix

(5).业务异常
业务执行异常,希望通过CommonServiceException抛出异常信息,而不是进入降级处理,解决方法是在@HystrixCommand注解里增加ignoreExceptions属性。

@Slf4j
@RestController
@RequestMapping("/films")
public class FilmController {
//获取电影列表降级方法
public ServerResponse findFilmListFallback(@RequestBody BasePageVO basePageVO) throws CommonServiceException {
return ServerResponse.createByErrorCodeMessage(500, "请求处理降级返回");
}

//获取电影列表
@HystrixCommand(fallbackMethod = "findFilmListFallback", commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50")
}, threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "10"),
@HystrixProperty(name = "keepAliveTimeMinutes", value = "1000"),
@HystrixProperty(name = "maxQueueSize", value = "10"),
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "8"),
@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "12"),
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "1500")
}, ignoreExceptions = {CommonServiceException.class})
@RequestMapping(value = "/findFilmList", method = RequestMethod.POST)
public ServerResponse findFilmList(@RequestBody BasePageVO basePageVO) throws CommonServiceException {
//检查入参
basePageVO.checkParam();
if (basePageVO.getPageSize() > 1000) {
//业务执行出现异常,触发fallback
throw new CommonServiceException(500, "pageSIze太大");
}

//调用逻辑层,获取返回参数
IPage<Film> results = filmService.findFilmList(basePageVO.getCurrentPage(), basePageVO.getPageSize());

return ServerResponse.createBySuccess(PageUtil.getPageResult(results));
}
}

启动项目,然后在postman中请求“localhost:8080/movies/film-api/films/findFilmList”,可以查询到相应的信息,测试结果如下图所示。

9.Hystrix实践篇_面试_02

2.Feign整合Hystrix(在hall服务工程中修改)
(1).依赖
Feign中包含了Hystrix,因此不需要引入依赖。

(2).引入配置

feign:
hystrix:
enabled: true

(3).Fallback开发
在feign目录下新建FilmFeignFallbackAPIImpl类,具体代码如下。

@Slf4j
@Service
public class FilmFeignFallbackAPIImpl implements FilmFeignAPI {
@Override
public ServerResponse findFilmListByHallId(Integer hallId) {
log.error("请求处理降级返回");
return ServerResponse.createByErrorCodeMessage(500, "请求处理降级返回");
}
}

在@FeignClient注解上添加fallback属性。

@FeignClient(name = "film.service", path = "/films",fallback = FilmFeignFallbackAPIImpl.class)
public interface FilmFeignAPI extends BaseFeignAPI {
//根据影厅id获取电影信息
@RequestMapping(value = "/findFilmListByHallId/{hallId}", method = RequestMethod.GET)
ServerResponse findFilmListByHallId(@PathVariable("hallId") Integer hallId);
}

(4).测试

不启动电影服务,模拟电影服务不可用触发fallback的场景,启动影厅服务,然后在postman中请求“localhost:8080/movies/hall-api/halls/findFilmListByHallIds”,可以查询到相应的信息,测试结果如下图所示。

9.Hystrix实践篇_面试_03


9.Hystrix实践篇_面试_04


由上图可知,影厅服务调用电影服务失败,触发fallback,一共触发6次。(5).hall服务工程目录结构

9.Hystrix实践篇_状态码_05

4.Zuul整合Hystrix(在zuul和film服务工程中修改)
(1).引入配置

hystrix:
command:
default:
execution:
isolation:
thread:
timoutInMilliseconds: 1000

(2).fallback开发
首先在项目目录“/src/main/java/com/steven/movies/zuul”下新建“/fallback”目录,并在fallback目录下新建FilmProviderFallback和HallProviderFallback类,具体代码如下。

@Slf4j
@Component
public class FilmProviderFallback implements FallbackProvider {
@Override
public String getRoute() {
return "film.service";
}

@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
//ClientHttpResponse的fallback状态码,返回HttpStatus
@NonNull
@Override
public HttpStatus getStatusCode() {
return HttpStatus.INTERNAL_SERVER_ERROR;
}

//ClientHttpResponse的fallback状态码,返回int
@Override
public int getRawStatusCode() {
return this.getStatusCode().value();
}

//ClientHttpResponse的fallback状态码,返回String
@NonNull
@Override
public String getStatusText() {
return this.getStatusCode().getReasonPhrase();
}

//回收资源方法,用于回收当前fallback逻辑开启的资源对象
@Override
public void close() {

}

//设置方法体,Zuul会将本方法返回的输入流数据读取,并且通过HttpServletResponse的输出流输出到客户端
@NonNull
@Override
public InputStream getBody() {
log.error("zuul time:{}",System.currentTimeMillis());
String result = "电影服务不可用";
return new ByteArrayInputStream(result.getBytes(StandardCharsets.UTF_8));
}

//设置响应头
@NonNull
@Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(new MediaType("application", "json", StandardCharsets.UTF_8));
return httpHeaders;
}
};
}
}
@Slf4j
@Component
public class HallProviderFallback implements FallbackProvider {
@Override
public String getRoute() {
return "hall.service";
}

@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
//ClientHttpResponse的fallback状态码,返回HttpStatus
@NonNull
@Override
public HttpStatus getStatusCode() {
return HttpStatus.INTERNAL_SERVER_ERROR;
}

//ClientHttpResponse的fallback状态码,返回int
@Override
public int getRawStatusCode() {
return this.getStatusCode().value();
}

//ClientHttpResponse的fallback状态码,返回String
@NonNull
@Override
public String getStatusText() {
return this.getStatusCode().getReasonPhrase();
}

//回收资源方法,用于回收当前fallback逻辑开启的资源对象
@Override
public void close() {

}

//设置方法体,Zuul会将本方法返回的输入流数据读取,并且通过HttpServletResponse的输出流输出到客户端
@NonNull
@Override
public InputStream getBody() {
String result = "影厅服务不可用";
return new ByteArrayInputStream(result.getBytes(StandardCharsets.UTF_8));
}

//设置响应头
@NonNull
@Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(new MediaType("application", "json", StandardCharsets.UTF_8));
return httpHeaders;
}
};
}
}

(3).film服务修改

@Slf4j
@RestController
@RequestMapping("/films")
public class FilmController {
@Autowired
private IFilmService filmService;

@Value("${server.port}")
private int port;

public ServerResponse findFilmListFallback(@RequestBody BasePageVO basePageVO) throws CommonServiceException {
log.error("film time:{}", System.currentTimeMillis());
return ServerResponse.createByErrorCodeMessage(500, "请求处理降级返回");
}

//获取电影列表
@HystrixCommand(fallbackMethod = "findFilmListFallback", commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "900"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50")
}, threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "10"),
@HystrixProperty(name = "keepAliveTimeMinutes", value = "1000"),
@HystrixProperty(name = "maxQueueSize", value = "10"),
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "8"),
@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "12"),
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "1500")
}, ignoreExceptions = {CommonServiceException.class})
@RequestMapping(value = "/findFilmList", method = RequestMethod.POST)
public ServerResponse findFilmList(@RequestBody BasePageVO basePageVO) throws CommonServiceException, InterruptedException {
//检查入参
basePageVO.checkParam();
if (basePageVO.getPageSize() > 1000) {
//休眠1秒,触发超时熔断
Thread.sleep(1000);
}

//调用逻辑层,获取返回参数
IPage<Film> results = filmService.findFilmList(basePageVO.getCurrentPage(), basePageVO.getPageSize());

return ServerResponse.createBySuccess(PageUtil.getPageResult(results));
}
}

(4).测试

启动项目,然后在postman中请求“localhost:8080/movies/film-api/films/findFilmList”,可以查询到相应的信息,测试结果如下图所示。

9.Hystrix实践篇_状态码_06


在postman中请求“localhost:8080/movies/hall-api/halls/findFilmListByHallIds”,可以查询到相应的信息,测试结果如下图所示。

9.Hystrix实践篇_java_07

(5).zuul服务工程目录结构

9.Hystrix实践篇_hystrix_08


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6