Hystrix集群及监控turbine
前面Dashboard演示的仅仅是单机服务监控,实际项目基本都是集群,所以这里集群监控用的是turbine。
说明:本篇博客基于上一篇的配置 springCould 之 Hystrix断路器
新建服务提供这集群项目(这是一个项目,通过不同配置达到集群的目的)和上片博客中microservice-book-provider-hystrix-1005一样copy就行了,下面是不同的部分
application.yml
---
server:
port: 1004
context-path: /
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/cpc?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: root
jpa:
hibernate:
ddl-auto: update
show-sql: true
application:
name: microservice-book
profiles: provider-hystrix-1004
eureka:
instance:
hostname: localhost
appname: microservice-book
instance-id: microservice-book:1004
prefer-ip-address: true
client:
service-url:
defaultZone: http://eureka2001.cpc.com:2001/eureka/,http://eureka2002.cpc.com:2002/eureka/,http://eureka2003.cpc.com:2003/eureka/
info:
groupId: com.cpc.testSpringcloud
artifactId: microservice-book-provider-hystrix-1004
version: 1.0-SNAPSHOT
userName: http://cpc.com
phone: 123456
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 1500
---
server:
port: 1005
context-path: /
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/cpc?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: root
jpa:
hibernate:
ddl-auto: update
show-sql: true
application:
name: microservice-book
profiles: provider-hystrix-1005
eureka:
instance:
hostname: localhost
appname: microservice-book
instance-id: microservice-book:1005
prefer-ip-address: true
client:
service-url:
defaultZone: http://eureka2001.cpc.com:2001/eureka/,http://eureka2002.cpc.com:2002/eureka/,http://eureka2003.cpc.com:2003/eureka/
info:
groupId: com.cpc.testSpringcloud
artifactId: microservice-book-provider-hystrix-1005
version: 1.0-SNAPSHOT
userName: http://cpc.com
phone: 123456
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 10000
---
server:
port: 1006
context-path: /
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/cpc?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: root
jpa:
hibernate:
ddl-auto: update
show-sql: true
application:
name: microservice-book
profiles: provider-hystrix-1006
eureka:
instance:
hostname: localhost
appname: microservice-book
instance-id: microservice-book:1006
prefer-ip-address: true
client:
service-url:
defaultZone: http://eureka2001.cpc.com:2001/eureka/,http://eureka2002.cpc.com:2002/eureka/,http://eureka2003.cpc.com:2003/eureka/
info:
groupId: com.cpc.testSpringcloud
artifactId: microservice-book-provider-hystrix-1006
version: 1.0-SNAPSHOT
userName: http://cpc.com
phone: 123456
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 10000
启动类:
package com.cpc.microservicebookproviderhystrix;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableCircuitBreaker //关键部分
@EntityScan("com.cpc.*.*")
@EnableEurekaClient
@SpringBootApplication
public class MicroserviceBookProviderHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceBookProviderHystrixApplication.class, args);
}
}
Run/Debug Configurations
消费者集群配置完成了
新建项目microservice-book-consumer-hystrix-turbine-91
pom.xml加下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-turbine</artifactId>
</dependency>
application.yml
server:
port: 91
context-path: /
eureka:
client:
service-url:
defaultZone: http://eureka2001.cpc.com:2001/eureka/,http://eureka2002.cpc.com:2002/eureka/,http://eureka2003.cpc.com:2003/eureka/
turbine:
app-config: microservice-book # 指定要监控的应用名称
clusterNameExpression: "'default'" #表示集群的名字为default
spring:
application:
name: turbine
启动类
package com.cpc.microservicebookconsumerhystrixturbine91;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.cloud.netflix.turbine.EnableTurbine;
@EnableTurbine
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class MicroserviceBookConsumerHystrixTurbine91Application {
public static void main(String[] args) {
SpringApplication.run(MicroserviceBookConsumerHystrixTurbine91Application.class, args);
}
}
测试
先启动三个eureka,然后把带刚刚配置带的 hystrix 的服务都启动;
microservice-book-consumer-80(消费者)
这个也启动,方便测试;启动dashboard服务,启动turbine服务;
http://localhost:91/turbine.stream 可以监控数据,实时ping 返回data
输入http://localhost:90/hystrix进入仪表盘,输入地址
点击 进入集群监控仪表:
服务降级
所谓降级,一般是从整体负荷考虑。就是当某个服务熔断之后,服务器将不再被调用此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值。这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强。
整体资源快不够了,忍痛将某些服务先关闭,待度过难关,再开启回来.例如:
假设银行有3个窗口A,B,C,每个窗口提供不同的业务,现在A窗口的服务人员,人手不够急需从C或者B窗口调人处理业务,C或者B窗口挂起暂停服务的牌子
服务降级处理是在客户端,也就是消费者(调用方)实现完成的,与服务端没有关系
服务熔断的做法需要一个方法就需要一个回复的方法,并且回复的方法和业务逻辑方法在一起,代码过于耦合,所以接下来试试这个服务降级的操作:
通用模块配置
服务降级要配合 feign 调用方式才能使用,降级是在消费者方做的 所以直接修改通用模块的代码,先写一个降级处理类,实现FallbackFactory<StudentClientService>
接口;
package com.cpc.common.service;
import com.cpc.common.entity.Book;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description: 这是降级处理类
* @Author: cpc
* @Date: 2019-11-22 18:34
* @Version: V1.0
*/
@Component // 不要忘记添加,不要忘记添加,千万不要忘记 这是一个巨大的坑
public class BookServiceFallbackFactory implements FallbackFactory<BookClientService> {
@Override
public BookClientService create(Throwable throwable) {
//实现BookClientService 这个接口,当调用服务端失败的时候就走这里面对应方法的逻辑
return new BookClientService() {
@Override
public Map<String, Object> hystrix() {
Map<String,Object> map=new HashMap<String,Object>();
map.put("code", 500);
map.put("info", "这是在客户端做服务降级");
return map;
}
@Override
public Book get(Integer id) {
return null;
}
@Override
public List<Book> list() {
return null;
}
@Override
public boolean save(Book book) {
return false;
}
@Override
public boolean delete(Integer id) {
return false;
}
@Override
public String ribbon() {
return null;
}
};
}
}
feign 调用接口:重点是在FeignClient
注解上加了fallbackFactory 这个参数
package com.cpc.common.service;
import com.cpc.common.entity.Book;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
import java.util.Map;
/**
* Book Feign接口客户端
* @author Administrator
*
*/
// fallbackFactory 是指定降级处理实现类
@FeignClient(value = "MICROSERVICE-BOOK", fallbackFactory = BookServiceFallbackFactory.class)
public interface BookClientService {
/**
* 根据id查询学生信息
* @param id
* @return
*/
@GetMapping(value="/book/get/{id}")
public Book get(@PathVariable("id") Integer id);
/**
* 查询学生信息
* @return
*/
@GetMapping(value="/book/list")
public List<Book> list();
/**
* 添加或者修改学生信息
* @param book
* @return
*/
@PostMapping(value="/book/save")
public boolean save(Book book);
/**
* 根据id删除学生信息
* @return
*/
@GetMapping(value="/book/delete/{id}")
public boolean delete(@PathVariable("id") Integer id);
@RequestMapping("/book/ribbon")
public String ribbon();
/**
* 这是测试服务熔断的
* @return
*/
@RequestMapping("/book/hystrix")
public Map<String, Object> hystrix();
}
microservice-feign-consumer-feign-80修改(具体的服务调用方)
BookConsumerController
package com.cpc.microservicebookconsumerfeign80.controller;
import com.cpc.common.entity.Book;
import com.cpc.common.service.BookClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/book")
public class BookConsumerController {
@Autowired
private BookClientService bookClientService;
@PostMapping(value = "/save")
private boolean save(Book book) {
return bookClientService.save(book);
}
@GetMapping(value = "/list")
public List<Book> list() {
return bookClientService.list();
}
@GetMapping(value = "/get/{id}")
public Book get(@PathVariable("id") Integer id) {
return bookClientService.get(id);
}
@GetMapping(value = "/delete/{id}")
public boolean delete(@PathVariable("id") Integer id) {
try {
bookClientService.delete(id);
return true;
} catch (Exception e) {
return false;
}
}
@RequestMapping("/ribbon")
public String ribbon(){
return bookClientService.ribbon();
}
@RequestMapping("/hystrix")
public Map<String, Object> hystrix(){
return bookClientService.hystrix();
}
}
启动类配置
package com.cpc.microservicebookconsumerfeign80;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.cpc"})
//注意这里,如果通用模块包名不同那么是可能无法将对应的类加入ioc容器,这个配置非常的重要
@ComponentScan(basePackages = {"com.cpc.common.service", "com.cpc.microservicebookconsumerfeign80"})
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class MicroserviceBookConsumerFeign80Application {
public static void main(String[] args) {
SpringApplication.run(MicroserviceBookConsumerFeign80Application.class, args);
}
}
application.yml 中添加如下配置
feign: #feign负载均衡启动 hystrix
hystrix:
enabled: true
测试
启动eureka集群,启动服务提供者集群,启动服务消费者,测试调用 http://localhost/book/hystrix,当服务提供者那边调用不到,或者超时异常的时候
消费者超时设置
使用Feign调用接口分两层,ribbon的调用和hystrix的调用,所以ribbon的超时时间和Hystrix的超时时间的结合就是Feign的超时时间
# 这是 ribbon 调用超时时间设置
ribbon:
ReadTimeout: 10000
ConnectTimeout: 9000
#hystrix的超时时间
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 9000
一般情况下 都是 ribbon 的超时时间(<)hystrix的超时时间(因为涉及到ribbon的重试机制)