SpringCloudNetflixHystrix
Spring Cloud Netflix Hystrix
服务短路(CircuitBreaker)
QPS: Query Per Second
TPS: Transaction Per Second
QPS: 经过全链路压测,计算单机极限QPS,集群 QPS = 单机 QPS * 集群机器数量 * 可靠性比率
全链路压测 除了压 极限QPS,还有错误数量
全链路:一个完整的业务流程操作
JMeter:可调整型比较灵活
Spring Cloud Hystrix Client
官网: https://github.com/Netflix/Hystrix
Reactive Java 框架:
- Java 9 Flow API
- Reactor
- RxJava(Reactive X)
激活 Hystrix
通过 @EnableHystrix 激活
Hystrix 配置信息wiki:https://github.com/Netflix/Hystrix/wiki/Configuration
注解方式(Annotation)
@RestController
public class HystrixDemoController {
private final static Random random = new Random();
/**
* 当{@link #helloWorld} 方法调用超时或失败时,
* fallback 方法{@link #errorContent()}作为替代返回
*
* @return
*/
@GetMapping("hello-world")
@HystrixCommand(fallbackMethod = "errorContent",
commandProperties = {@HystrixProperty(
name = "execution.isolation.thread.timeoutInMilliseconds",
value = "100"
)}
)
public String helloWorld() throws Exception {
// 如果随机时间 大于 100 ,那么触发容错
int value = random.nextInt(200);
System.out.println("helloWorld() costs "+value+" ms.");
Thread.sleep(value);
return "Hello,World";
}
public String errorContent() {
return "Fault";
}
}
编程方式
/**
* 当{@link #helloWorld} 方法调用超时或失败时,
* fallback 方法{@link #errorContent()}作为替代返回
*
* @return
*/
@GetMapping("hello-world-2")
public String helloWorld2() {
return new HelloWorldCommand().execute();
}
/**
* 编程方式
*/
private class HelloWorldCommand extends com.netflix.hystrix.HystrixCommand<String> {
protected HelloWorldCommand() {
super(HystrixCommandGroupKey.Factory.asKey("HelloWorld"), 100);
}
@Override
protected String run() throws Exception {
// 如果随机时间 大于 100 ,那么触发容错
int value = random.nextInt(200);
System.out.println("helloWorld() costs " + value + " ms.");
Thread.sleep(value);
return "Hello,World";
}
//容错执行
protected String getFallback() {
return HystrixDemoController.this.errorContent();
}
}
其他 Java 执行方式
Future
public class FutureDemo {
public static void main(String[] args) {
Random random = new Random();
ExecutorService service = Executors.newFixedThreadPool(1);
Future<String> future = service.submit(() -> { // 正常流程
// 如果随机时间 大于 100 ,那么触发容错
int value = random.nextInt(200);
System.out.println("helloWorld() costs " + value + " ms.");
Thread.sleep(value);
return "Hello,World";
});
try {
future.get(100, TimeUnit.MILLISECONDS);
} catch (Exception e) {
// 超时流程
System.out.println("超时保护!");
}
service.shutdown();
}
}
RxJava
public class RxJavaDemo {
public static void main(String[] args) {
Random random = new Random();
Single.just("Hello,World") // just 发布数据
// 订阅的线程池 immediate = Thread.currentThread()
.subscribeOn(Schedulers.immediate())
.subscribe(new Observer<String>() {
@Override
public void onCompleted() { // 正常结束流程
System.out.println("执行结束!");
}
@Override
public void onError(Throwable e) { // 异常流程(结束)
System.out.println("熔断保护!");
}
@Override
public void onNext(String s) { // 数据消费 s = "Hello,World"
// 如果随机时间 大于 100 ,那么触发容错
int value = random.nextInt(200);
if (value > 100) {
throw new RuntimeException("Timeout!");
}
System.out.println("helloWorld() costs " + value + " ms.");
}
});
}
}
Health Endpoint(/health)
{
status: "UP",
diskSpace: {
status: "UP",
total: 500096983040,
free: 304113217536,
threshold: 10485760
},
refreshScope: {
status: "UP"
},
hystrix: {
status: "UP"
}
}
激活熔断保护
@EnableCircuitBreaker 激活 :@EnableHystrix + Spring Cloud 功能
@EnableHystrix 激活,没有一些 Spring Cloud 功能,如 /hystrix.stream 端点
Hystrix Endpoint(/hystrix.stream)
data: {
"type": "HystrixThreadPool",
"name": "HystrixDemoController",
"currentTime": 1509545957972,
"currentActiveCount": 0,
"currentCompletedTaskCount": 14,
"currentCorePoolSize": 10,
"currentLargestPoolSize": 10,
"currentMaximumPoolSize": 10,
"currentPoolSize": 10,
"currentQueueSize": 0,
"currentTaskCount": 14,
"rollingCountThreadsExecuted": 5,
"rollingMaxActiveThreads": 1,
"rollingCountCommandRejections": 0,
"propertyValue_queueSizeRejectionThreshold": 5,
"propertyValue_metricsRollingStatisticalWindowInMilliseconds": 10000,
"reportingHosts": 1
}
Hystrix Dashboard
激活 Dashboard
@EnableHystrixDashboard
server.port=7070
@SpringBootApplication
@EnableHystrixDashboard
public class SpringCloudHystrixDashboardDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudHystrixDashboardDemoApplication.class, args);
}
}
查看监控结果:
actuator hystrix stream:
最开始只显示 ping,请求 /hello-world 或者 /hello-world2 后,有请求数据显示

hystrix dashboard:

整合 Netflix Turbine
引入 maven 依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-turbine</artifactId> </dependency>激活 trubine
使用注解
@EnableTurbine配置 eureka
在 application.properties 中配置
server.port=8080 management.server.port=8081 eureka.client.service-url.defaultZone=\ http://localhost:9090/eureka eureka.instance.metadata-map.management.port = \ ${management.server.port} # turbine 配置 turbine.aggregator.cluster-config=CUSTOMERS turbine.app-config=customer使用浏览器访问
localhost:8081/actuator/hystrix.stream

localhost:8080/turbine.stream?cluster=CUSTOMERS

hystrix dashboard: localhost:7070/hystrix

问答部分
ribbon 是用来做什么的,只能负载均衡吗?
答: 主要用于客户端负载
Kafka 与 ActiveMQ?
答:ActiveMQ 相对来说是比较完善的中间件,Kafka 在能力上比较灵活,它放弃不少约束,性能相对较好
要提交 java 的基础,有什么好的书籍推荐吗?
答:起始基本经典的书要读,Java编程思想、Effective Java 1和2。相关类名,比如集合,要选择读。
注释 {@link} 怎么用,什么作用啊,怎么弄出来的,没看清楚
答:@JavaDoc 一部分,通过 Java 注释生成Html 文档。
@link 应用某个类,比如 {@link String}
@since 从哪个版本开始
@author 作者
里面嵌入 java 代码spring cloud 的config配置,获取到的 git 中的 properties 文件的一些属性(比如,my.name),可以直接在其他 spring 的 xml 中使用吗?需要怎样配置?
答:利用注解 @ImportResource("abc.xml")
abc.xml
<bean id="person" class="com.gupao.domain.Person"> <property name="name" value="${my.name}"/> </bean>启动类:Main.java
@ImportResource("abc.xml") @SpringBootApplication public class Main{ public static void main(String[] args){ SpringApplication.run(Main.class, args); } }将实时数据缓存到 Redis,再由 Storm 去消费,这种做法好吗?有没有更好的方案
答:Storm 消费数据需要强持久性,Redis 相比 DB 逊色一点。
spring boot 中用 new SpringApplicationBuilder().sources(AppConfig.class) 方式启动,是先加载 AppConfig 还是先加载配置文件?
答:AppConfig 是一个配置 @Configuration Class,那么配置文件是一个外部资源,其实不会相互影响。
如果 AppConfig 中增加了 @PropertySource 或者 @PropertySources 的话,会优先加载 @PropertySource 中的配置资源