文档章节

聊聊spring cloud netflix的HystrixCommands

go4it
 go4it
发布于 06/22 23:45
字数 884
阅读 13
收藏 1
点赞 0
评论 0

本文主要研究一下spring cloud netflix的HystrixCommands。

maven

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

这个组件对hystrix进行了封装了,2.0.0.RELEASE全面支持了Reactor的Reactive Streams。

spring-cloud-starter-netflix-hystrix/pom.xml

spring-cloud-starter-netflix-hystrix-2.0.0.RELEASE.jar!/META-INF/maven/org.springframework.cloud/spring-cloud-starter-netflix-hystrix/pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix</artifactId>
		<version>2.0.0.RELEASE</version>
	</parent>
	<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
	<name>Spring Cloud Starter Netflix Hystrix</name>
	<description>Spring Cloud Starter Netflix Hystrix</description>
	<url>https://projects.spring.io/spring-cloud</url>
	<organization>
		<name>Pivotal Software, Inc.</name>
		<url>https://www.spring.io</url>
	</organization>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-netflix-core</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-netflix-ribbon</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-archaius</artifactId>
		</dependency>
		<dependency>
			<groupId>com.netflix.hystrix</groupId>
			<artifactId>hystrix-core</artifactId>
		</dependency>
		<dependency>
			<groupId>com.netflix.hystrix</groupId>
			<artifactId>hystrix-serialization</artifactId>
		</dependency>
		<dependency>
			<groupId>com.netflix.hystrix</groupId>
			<artifactId>hystrix-metrics-event-stream</artifactId>
		</dependency>
		<dependency>
			<groupId>com.netflix.hystrix</groupId>
			<artifactId>hystrix-javanica</artifactId>
		</dependency>
		<dependency>
			<groupId>io.reactivex</groupId>
			<artifactId>rxjava-reactive-streams</artifactId>
		</dependency>
	</dependencies>
</project>

这里要讲的HystrixCommands在spring-cloud-netflix-core这个组件里

HystrixCommands

spring-cloud-netflix-core-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/hystrix/HystrixCommands.java

/**
 * Utility class to wrap a {@see Publisher} in a {@see HystrixObservableCommand}. Good for
 * use in a Spring WebFlux application. Allows more flexibility than the @HystrixCommand
 * annotation.
 * @author Spencer Gibb
 */
public class HystrixCommands {

	public static <T> PublisherBuilder<T> from(Publisher<T> publisher) {
		return new PublisherBuilder<>(publisher);
	}

	public static class PublisherBuilder<T> {
		private final Publisher<T> publisher;
		private String commandName;
		private String groupName;
		private Publisher<T> fallback;
		private Setter setter;
		private HystrixCommandProperties.Setter commandProperties;
		private boolean eager = false;
		private Function<HystrixObservableCommand<T>, Observable<T>> toObservable;

		public PublisherBuilder(Publisher<T> publisher) {
			this.publisher = publisher;
		}

		public PublisherBuilder<T> commandName(String commandName) {
			this.commandName = commandName;
			return this;
		}

		public PublisherBuilder<T> groupName(String groupName) {
			this.groupName = groupName;
			return this;
		}

		public PublisherBuilder<T> fallback(Publisher<T> fallback) {
			this.fallback = fallback;
			return this;
		}

		public PublisherBuilder<T> setter(Setter setter) {
			this.setter = setter;
			return this;
		}

		public PublisherBuilder<T> commandProperties(
				HystrixCommandProperties.Setter commandProperties) {
			this.commandProperties = commandProperties;
			return this;
		}

		public PublisherBuilder<T> commandProperties(
				Function<HystrixCommandProperties.Setter, HystrixCommandProperties.Setter> commandProperties) {
			if (commandProperties == null) {
				throw new IllegalArgumentException(
						"commandProperties must not both be null");
			}
			return this.commandProperties(
					commandProperties.apply(HystrixCommandProperties.Setter()));
		}

		public PublisherBuilder<T> eager() {
			this.eager = true;
			return this;
		}

		public PublisherBuilder<T> toObservable(Function<HystrixObservableCommand<T>, Observable<T>> toObservable) {
			this.toObservable = toObservable;
			return this;
		}

		public Publisher<T> build() {
			if (!StringUtils.hasText(commandName) && setter == null) {
				throw new IllegalStateException("commandName and setter can not both be empty");
			}
			Setter setterToUse = getSetter();

			PublisherHystrixCommand<T> command = new PublisherHystrixCommand<>(setterToUse, this.publisher, this.fallback);

			Observable<T> observable = getObservableFunction().apply(command);

			return RxReactiveStreams.toPublisher(observable);
		}

		public Function<HystrixObservableCommand<T>, Observable<T>> getObservableFunction() {
			Function<HystrixObservableCommand<T>, Observable<T>> observableFunc;

			if (this.toObservable != null) {
				observableFunc = this.toObservable;
			} else if (this.eager) {
				observableFunc = cmd -> cmd.observe();
			} else { // apply a default onBackpressureBuffer if not eager
				observableFunc = cmd -> cmd.toObservable().onBackpressureBuffer();
			}
			return observableFunc;
		}

		public Setter getSetter() {
			Setter setterToUse;
			if (this.setter != null) {
				setterToUse = this.setter;
			} else {
				String groupNameToUse;
				if (StringUtils.hasText(this.groupName)) {
					groupNameToUse = this.groupName;
				} else {
					groupNameToUse = commandName + "group";
				}

				HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey(groupNameToUse);
				HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey(this.commandName);
				HystrixCommandProperties.Setter commandProperties = this.commandProperties != null
						? this.commandProperties
						: HystrixCommandProperties.Setter();
				setterToUse = Setter.withGroupKey(groupKey).andCommandKey(commandKey)
						.andCommandPropertiesDefaults(commandProperties);
			}
			return setterToUse;
		}

		public Flux<T> toFlux() {
			return Flux.from(build());
		}

		public Mono<T> toMono() {
			return Mono.from(build());
		}

	}

	private static class PublisherHystrixCommand<T> extends HystrixObservableCommand<T> {

		private Publisher<T> publisher;
		private Publisher<T> fallback;

		protected PublisherHystrixCommand(Setter setter, Publisher<T> publisher,
				Publisher<T> fallback) {
			super(setter);
			this.publisher = publisher;
			this.fallback = fallback;
		}

		@Override
		protected Observable<T> construct() {
			return RxReactiveStreams.toObservable(publisher);
		}

		@Override
		protected Observable<T> resumeWithFallback() {
			if (this.fallback != null) {
				return RxReactiveStreams.toObservable(this.fallback);
			}
			return super.resumeWithFallback();
		}
	}
}

从类注释可以看到这个类就是为了方便webflux应用使用hystrix而设计的。

实例

    @Test
    public void testHystrixFallback() throws InterruptedException {
        Mono<String> delayMono = Mono.just("hello")
                .delayElement(Duration.ofMillis(500));
        Mono<String> result = HystrixCommands.from(delayMono)
                .commandName("demoCmd")
                .groupName("demoGroup")
                .eager()
                .commandProperties(HystrixCommandProperties.Setter()
                        .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
                        .withExecutionTimeoutInMilliseconds(1000)
                )
                .fallback(Mono.just("from fallback"))
                .toMono();

        System.out.println(result.block());

    }
  • HystrixCommands.from方法可以对Publisher进行hystrix包装
  • commandName用于指定hystrix的command名称
  • groupName用于指定hystrix的group名称
  • eager是默认方式,表示使用的是observe()方法,相当于hot Observable,只能消费从订阅时刻之后的数据,lazy使用的是toObservable()方法,相当于cold Observable,可以消费订阅之前的数据。
  • commandProperties用于指定command的属性,比如executionIsolationStrategy、executionTimeoutInMilliseconds
  • fallback用于指定fallback的操作

另外配置文件也可以指定默认的参数,比如

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds : 6000
      circuitBreaker:
        sleepWindowInMilliseconds: 10000
      metrics:
        rollingStats:
          timeInMilliseconds : 18000

小结

HystrixCommands就是spring cloud对netflix hystrix的包装,以方便webflux里头使用hystrix,就省得再去使用AOP技术了。

doc

© 著作权归作者所有

共有 人打赏支持
go4it
粉丝 51
博文 676
码字总数 477967
作品 0
深圳
聊聊spring cloud的HystrixCircuitBreakerConfiguration

序 本文主要研究一下spring cloud的HystrixCircuitBreakerConfiguration HystrixCircuitBreakerConfiguration spring-cloud-netflix-core-2.0.0.RELEASE-sources.jar!/org/springframework/......

go4it
06/24
0
0
聊聊eureka client的shutdown

序 本文主要研究一下eureka client的shutdown EurekaRegistration spring-cloud-netflix-eureka-client-2.0.0.RC1-sources.jar!/org/springframework/cloud/netflix/eureka/EurekaClientAuto......

go4it
05/04
0
0
聊聊ribbon的超时时间设置

序 本文主要研究一下ribbon的超时时间设置 配置 实例 RibbonClientConfiguration spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/Ribb......

go4it
07/20
0
0
聊聊EurekaRibbonClientConfiguration

序 本文主要研究一下EurekaRibbonClientConfiguration EurekaRibbonClientConfiguration spring-cloud-netflix-eureka-client-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netfl......

go4it
07/21
0
0
聊聊eureka的ZoneAffinityServerListFilter

序 本文主要研究一下eureka的ZoneAffinityServerListFilter ZoneAffinityServerListFilter ribbon-loadbalancer-2.2.5-sources.jar!/com/netflix/loadbalancer/ZoneAffinityServerListFilte......

go4it
05/22
0
0
聊聊spring cloud eureka的instanceEnabledOnit属性

序 本文主要研究下spring cloud eureka的instanceEnabledOnit属性 EurekaInstanceConfigBean spring-cloud-netflix-eureka-client-2.0.0.RC1-sources.jar!/org/springframework/cloud/netfl......

go4it
05/05
0
0
关于Eureka 2.x,别再人云亦云了!

原文: ,转载请说明出处。 最近朋友圈被Eureka 2.x停止开发的新闻刷屏,例如: Eureka 2.0 开源工作宣告停止,继续使用风险自负 凉凉了,Eureka 宣布闭源,Spring Cloud 何去何从? 关于第二...

周立_ITMuch
07/11
0
13
聊聊RibbonLoadBalancerClient的choose方法

序 本文主要研究一下RibbonLoadBalancerClient的choose方法 RibbonLoadBalancerClient.choose spring-cloud-netflix-ribbon-2.0.0.RC1-sources.jar!/org/springframework/cloud/netflix/rib......

go4it
05/28
0
0
聊聊spring cloud的AbstractLoadBalancingClient

序 本文主要研究一下spring cloud的AbstractLoadBalancingClient AbstractLoadBalancingClient spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netfli......

go4it
07/18
0
0
聊聊spring cloud的LoadBalancerAutoConfiguration

序 本文主要研究一下spring cloud的LoadBalancerAutoConfiguration RibbonAutoConfiguration spring-cloud-netflix-ribbon-2.0.0.RC2-sources.jar!/org/springframework/cloud/netflix/ribb......

go4it
07/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

回想过往,分析当下,着眼未来

好久没有真正的在纸质笔记本上写过东西了,感觉都快不会写字了,笔画都不知道怎么写了。接下来就说说咱们的正事。 2018年7月22日,我做了一个决定,那就是去参加安全培训(可能是我职业生涯中...

yeahlife
21分钟前
0
0
关于工作中的人际交往

关于工作中的人际交往 Intro 写了篇发泄情绪的博客,但不会发布出来。 大概就是,要么忍,要么滚。 以及一些不那么符合社会主义核心价值观,不满于大资本家与小资本家剥削的废话。

uniqptr
26分钟前
0
0
springMVC的流程

1.用户发送请求至前端控制器DispatcherServlet 2.DispatcherServlet收到请求调用HandlerMapping处理器映射器。 3.处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(...

JavaSon712
42分钟前
0
0
大数据教程(3.2):Linux系统软件安装之自动化脚本

博主前面文章有介绍过软件的安装,可以帮助IT人员顺利的完成功能软件安装;但是,对于我们运维人员或者需要管理软件安装的项目经理来说,有些应用一次行需要搭建很多台相同的软件环境(如tom...

em_aaron
今天
0
0
Spring Boot 2.0.3 JDBC整合Oracle 12

整合步骤 1. Oracle驱动引入 Oracle驱动一般不能通过maven仓库直接下载得到,需自行下载并导入到项目的lib目录下,建议通过如下pom依赖引入下载的Oracle驱动 <!-- Oracle 驱动 -->...

OSC_fly
今天
0
0
java 8 并行流 - 1

下面创建一个并行流,与顺序流 //顺序流Stream.iterate(0L, i -> i + 1) .limit(Integer.MAX_VALUE) .reduce(0L, Long::sum);//并行流Stream.iterate(0L, i -> i......

Canaan_
今天
0
0
数据结构与算法5

二分法采用向下取整的方法 使用有序数组的好处是查找的速度比无序数组快的多,不好的方面是因为要将所有靠后的数据移开,所以速度较慢,有序数组和无序数组的删除操作都很慢。 有序数组在查找...

沉迷于编程的小菜菜
昨天
1
1
SpringBoot | 第十一章:Redis的集成和简单使用

前言 上几节讲了利用Mybatis-Plus这个第三方的ORM框架进行数据库访问,在实际工作中,在存储一些非结构化或者缓存一些临时数据及热点数据时,一般上都会用上mongodb和redis进行这方面的需求。...

oKong
昨天
5
0
对基于深度神经网络的Auto Encoder用于异常检测的一些思考

一、前言 现实中,大部分数据都是无标签的,人和动物多数情况下都是通过无监督学习获取概念,故而无监督学习拥有广阔的业务场景。举几个场景:网络流量是正常流量还是攻击流量、视频中的人的...

冷血狂魔
昨天
0
0
并发设计之A系统调用B系统

A-->B A在发送请求之前,用乐观锁,减少对B的重复调用,这样一定程度上是幂等性。 比如A系统支付功能,要调用B系统进行支付操作,但是前端对"支付"按钮不进行控制,即用户会不断多次点击支付...

汉斯-冯-拉特
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部