(三) Spring Cloud - 断路器+(普通调用和feign封装调用)
1. Ribbon+Hystrix(断路器), 普通调用方式
pom.xml加入两个Hystrix依赖maven
-
<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> -
<groupId>com.sample</groupId> -
<artifactId>2017-Netflix_Ribbon</artifactId> -
<version>1.0.1-SNAPSHOT</version> -
<packaging>war</packaging> -
<build> -
<plugins> -
<plugin> -
<groupId>org.apache.maven.plugins</groupId> -
<artifactId>maven-compiler-plugin</artifactId> -
<version>3.3</version> -
<configuration> -
<!-- 指定source和target的版本 --> -
<source>1.8</source> -
<target>1.8</target> -
</configuration> -
</plugin> -
</plugins> -
</build> -
<parent> -
<groupId>org.springframework.boot</groupId> -
<artifactId>spring-boot-starter-parent</artifactId> -
<version>1.5.2.RELEASE</version> -
</parent> -
<dependencyManagement> -
<dependencies> -
<dependency> -
<groupId>org.springframework.cloud</groupId> -
<artifactId>spring-cloud-dependencies</artifactId> -
<version>Dalston.RELEASE</version> -
<type>pom</type> -
<scope>import</scope> -
</dependency> -
</dependencies> -
</dependencyManagement> -
<dependencies> -
<dependency> -
<groupId>org.springframework.cloud</groupId> -
<artifactId>spring-cloud-starter-config</artifactId> -
</dependency> -
<dependency> -
<groupId>org.springframework.cloud</groupId> -
<artifactId>spring-cloud-starter-eureka</artifactId> -
</dependency> -
<dependency> -
<groupId>org.springframework.cloud</groupId> -
<artifactId>spring-cloud-starter-hystrix</artifactId> -
</dependency> -
<dependency> -
<groupId>com.netflix.hystrix</groupId> -
<artifactId>hystrix-javanica</artifactId> -
</dependency> -
</dependencies> -
</project>
Ribbon启动的boot application,修改如下
-
package com.jack.ssm; -
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.client.loadbalancer.LoadBalanced; -
import org.springframework.context.annotation.Bean; -
import org.springframework.web.client.RestTemplate; -
/** -
* ClassName:RibbonApplication.java -
* Date: 2017年5月13日下午5:06:00 -
* @author Jack.Huang -
* @version V1.0 -
* @since JDK 1.7.0_60/JDK 1.8.0_45 -
*/ -
@SpringBootApplication -
@EnableDiscoveryClient -
@EnableCircuitBreaker // 注解开启断路器功能 -
public class RibbonApplication { -
@Bean -
@LoadBalanced -
RestTemplate restTemplate() { -
return new RestTemplate(); -
} -
public static void main(String[] args) { -
SpringApplication.run(RibbonApplication.class, args); -
} -
}
-
package com.jack.ssm.controller; -
import org.springframework.beans.factory.annotation.Autowired; -
import org.springframework.web.bind.annotation.RequestMapping; -
import org.springframework.web.bind.annotation.RequestMethod; -
import org.springframework.web.bind.annotation.RestController; -
import org.springframework.web.client.RestTemplate; -
import com.jack.ssm.service.ComputeService; -
/** -
* ClassName:ConsumerController.java -
* Date: 2017年5月13日下午5:10:00 -
* @author Jack.Huang -
* @version V1.0 -
* @since JDK 1.7.0_60/JDK 1.8.0_45 -
*/ -
@RestController -
public class ConsumerController { -
/* -
* 没有使用断路器之前的代码 -
* -
@Autowired -
RestTemplate restTemplate; -
@RequestMapping(value = "/ribbonCallAddService", method = RequestMethod.GET) -
public String add() { -
// return restTemplate.getForEntity("http://COMPUTE-SERVICE/add?a=10&b=20", String.class).getBody(); -
return restTemplate.getForEntity("http://NETFLIX-SERVICE/add?a=10&b=20", String.class).getBody(); -
} -
*/ -
/* -
* 使用断路器之后的代码 -
*/ -
@Autowired -
private ComputeService computeService; -
@RequestMapping(value = "/ribbonCallAddService", method = RequestMethod.GET) -
public String add() { -
return computeService.addService(); -
} -
}
-
package com.jack.ssm.service; -
import org.springframework.beans.factory.annotation.Autowired; -
import org.springframework.stereotype.Service; -
import org.springframework.web.client.RestTemplate; -
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; -
/** -
* ClassName:ComputeService.java -
* Date: 2017年5月15日下午5:18:45 -
* @author Jack.Huang -
* @version V1.0 -
* @since JDK 1.7.0_60/JDK 1.8.0_45 -
*/ -
@Service -
public class ComputeService { -
@Autowired -
RestTemplate restTemplate; -
@HystrixCommand(fallbackMethod = "addServiceFallback") -
public String addService() { -
return restTemplate.getForEntity("http://NETFLIX-SERVICE/add?a=10&b=20", String.class).getBody(); -
} -
public String addServiceFallback() { -
return "Error sevice"; -
} -
}
调用链接:http://localhost:8000/ribbonCallAddService
2. Feign+Hystrix(断路器)调用方式
pom.xml, feign的依赖已经引入了hystrix,无需再引入也可以实现断路器
-
<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> -
<groupId>com.sample</groupId> -
<artifactId>2017-Netflix_Feign</artifactId> -
<version>1.0.1-SNAPSHOT</version> -
<packaging>war</packaging> -
<build> -
<plugins> -
<plugin> -
<groupId>org.apache.maven.plugins</groupId> -
<artifactId>maven-compiler-plugin</artifactId> -
<version>3.3</version> -
<configuration> -
<!-- 指定source和target的版本 --> -
<source>1.8</source> -
<target>1.8</target> -
</configuration> -
</plugin> -
</plugins> -
</build> -
<parent> -
<groupId>org.springframework.boot</groupId> -
<artifactId>spring-boot-starter-parent</artifactId> -
<version>1.5.2.RELEASE</version> -
</parent> -
<dependencyManagement> -
<dependencies> -
<dependency> -
<groupId>org.springframework.cloud</groupId> -
<artifactId>spring-cloud-dependencies</artifactId> -
<!-- <version>Camden.SR6</version> --> -
<version>Dalston.RELEASE</version> -
<type>pom</type> -
<scope>import</scope> -
</dependency> -
</dependencies> -
</dependencyManagement> -
<dependencies> -
<dependency> -
<groupId>org.springframework.cloud</groupId> -
<artifactId>spring-cloud-starter-config</artifactId> -
</dependency> -
<dependency> -
<groupId>org.springframework.cloud</groupId> -
<artifactId>spring-cloud-starter-eureka</artifactId> -
</dependency> -
<dependency> -
<groupId>org.springframework.cloud</groupId> -
<artifactId>spring-cloud-starter-feign</artifactId> -
</dependency> -
<!-- <dependency> -
<groupId>org.springframework.cloud</groupId> -
<artifactId>spring-cloud-starter-hystrix</artifactId> -
</dependency> --> -
</dependencies> -
</project>
application.yml, Dalston.RELEASE版本默认关闭hystrix, 其它版本则是默认打开
https://github.com/spring-cloud/spring-cloud-netflix/issues/1277这是spring社区关于为什么默认关闭的解析
-
server: -
port: 8001 -
spring: -
application: -
name: feign-consumer -
eureka: -
service-url: -
defaultZone: http://localhost:8761/eureka/ -
feign: -
hystrix: -
enabled: true
-
package com.jack.ssm.service; -
import org.springframework.cloud.netflix.feign.FeignClient; -
import org.springframework.web.bind.annotation.RequestMapping; -
import org.springframework.web.bind.annotation.RequestMethod; -
import org.springframework.web.bind.annotation.RequestParam; -
import com.jack.ssm.service.hystrix.ComputeServiceHystrix; -
/** -
* ClassName:ComputeService.java -
* Date: 2017年5月13日下午10:06:07 -
* @author Jack.Huang -
* @version V1.0 -
* @since JDK 1.7.0_60/JDK 1.8.0_45 -
*/ -
@FeignClient(name = "NETFLIX-SERVICE", fallback = ComputeServiceHystrix.class) -
public interface ComputeService { -
@RequestMapping(method = RequestMethod.GET, value = "/add") -
String add(@RequestParam(value = "a") Integer a, @RequestParam(value = "b") Integer b); -
}
-
package com.jack.ssm.service.hystrix; -
import org.springframework.stereotype.Component; -
import org.springframework.web.bind.annotation.RequestParam; -
import com.jack.ssm.service.ComputeService; -
/** -
* ClassName:ComputeClientHystrix.java -
* Date: 2017年5月15日下午4:14:54 -
* @author Jack.Huang -
* @version V1.0 -
* @since JDK 1.7.0_60/JDK 1.8.0_45 -
*/ -
@Component -
public class ComputeServiceHystrix implements ComputeService { -
@Override -
public String add(@RequestParam(value = "a") Integer a, @RequestParam(value = "b") Integer b) { -
return "Error service or service both down!"; -
} -
}
调用链接http://localhost:8001/feignCallAddService
3.至于feign哪里默认关闭hystrix的源码如下
-
/* -
* Copyright 2013-2016 the original author or authors. -
* -
* Licensed under the Apache License, Version 2.0 (the "License"); -
* you may not use this file except in compliance with the License. -
* You may obtain a copy of the License at -
* -
* http://www.apache.org/licenses/LICENSE-2.0 -
* -
* Unless required by applicable law or agreed to in writing, software -
* distributed under the License is distributed on an "AS IS" BASIS, -
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
* See the License for the specific language governing permissions and -
* limitations under the License. -
*/ -
package org.springframework.cloud.netflix.hystrix.security; -
import javax.annotation.PostConstruct; -
import org.springframework.beans.factory.annotation.Autowired; -
import org.springframework.boot.autoconfigure.condition.AllNestedConditions; -
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -
import org.springframework.cloud.netflix.hystrix.security.HystrixSecurityAutoConfiguration.HystrixSecurityCondition; -
import org.springframework.context.annotation.Conditional; -
import org.springframework.context.annotation.Configuration; -
import org.springframework.security.core.context.SecurityContext; -
import com.netflix.hystrix.Hystrix; -
import com.netflix.hystrix.strategy.HystrixPlugins; -
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; -
import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier; -
import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook; -
import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher; -
import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy; -
/** -
* @author Daniel Lavoie -
*/ -
@Configuration -
@Conditional(HystrixSecurityCondition.class) -
@ConditionalOnClass({ Hystrix.class, SecurityContext.class }) -
public class HystrixSecurityAutoConfiguration { -
@Autowired(required = false) -
private HystrixConcurrencyStrategy existingConcurrencyStrategy; -
@PostConstruct -
public void init() { -
// Keeps references of existing Hystrix plugins. -
HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance() -
.getEventNotifier(); -
HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance() -
.getMetricsPublisher(); -
HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance() -
.getPropertiesStrategy(); -
HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance() -
.getCommandExecutionHook(); -
HystrixPlugins.reset(); -
// Registers existing plugins excepts the Concurrent Strategy plugin. -
HystrixPlugins.getInstance().registerConcurrencyStrategy( -
new SecurityContextConcurrencyStrategy(existingConcurrencyStrategy)); -
HystrixPlugins.getInstance().registerEventNotifier(eventNotifier); -
HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher); -
HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy); -
HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook); -
} -
static class HystrixSecurityCondition extends AllNestedConditions { -
public HystrixSecurityCondition() { -
super(ConfigurationPhase.REGISTER_BEAN); -
} -
@ConditionalOnProperty(name = "feign.hystrix.enabled", matchIfMissing = false) -
static class HystrixEnabled { -
} -
@ConditionalOnProperty(name = "hystrix.shareSecurityContext") -
static class ShareSecurityContext { -
} -
} -
}
-
/* -
* Copyright 2013-2016 the original author or authors. -
* -
* Licensed under the Apache License, Version 2.0 (the "License"); -
* you may not use this file except in compliance with the License. -
* You may obtain a copy of the License at -
* -
* http://www.apache.org/licenses/LICENSE-2.0 -
* -
* Unless required by applicable law or agreed to in writing, software -
* distributed under the License is distributed on an "AS IS" BASIS, -
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
* See the License for the specific language governing permissions and -
* limitations under the License. -
*/ -
package org.springframework.cloud.netflix.feign; -
import java.util.ArrayList; -
import java.util.List; -
import org.springframework.beans.factory.ObjectFactory; -
import org.springframework.beans.factory.annotation.Autowired; -
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -
import org.springframework.boot.autoconfigure.web.HttpMessageConverters; -
import org.springframework.cloud.netflix.feign.support.ResponseEntityDecoder; -
import org.springframework.cloud.netflix.feign.support.SpringDecoder; -
import org.springframework.cloud.netflix.feign.support.SpringEncoder; -
import org.springframework.cloud.netflix.feign.support.SpringMvcContract; -
import org.springframework.context.annotation.Bean; -
import org.springframework.context.annotation.Configuration; -
import org.springframework.context.annotation.Scope; -
import org.springframework.core.convert.ConversionService; -
import org.springframework.format.support.DefaultFormattingConversionService; -
import org.springframework.format.support.FormattingConversionService; -
import com.netflix.hystrix.HystrixCommand; -
import feign.Contract; -
import feign.Feign; -
import feign.Logger; -
import feign.Retryer; -
import feign.codec.Decoder; -
import feign.codec.Encoder; -
import feign.hystrix.HystrixFeign; -
/** -
* @author Dave Syer -
* @author Venil Noronha -
*/ -
@Configuration -
public class FeignClientsConfiguration { -
@Autowired -
private ObjectFactory<HttpMessageConverters> messageConverters; -
@Autowired(required = false) -
private List<AnnotatedParameterProcessor> parameterProcessors = new ArrayList<>(); -
@Autowired(required = false) -
private List<FeignFormatterRegistrar> feignFormatterRegistrars = new ArrayList<>(); -
@Autowired(required = false) -
private Logger logger; -
@Bean -
@ConditionalOnMissingBean -
public Decoder feignDecoder() { -
return new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)); -
} -
@Bean -
@ConditionalOnMissingBean -
public Encoder feignEncoder() { -
return new SpringEncoder(this.messageConverters); -
} -
@Bean -
@ConditionalOnMissingBean -
public Contract feignContract(ConversionService feignConversionService) { -
return new SpringMvcContract(this.parameterProcessors, feignConversionService); -
} -
@Bean -
public FormattingConversionService feignConversionService() { -
FormattingConversionService conversionService = new DefaultFormattingConversionService(); -
for (FeignFormatterRegistrar feignFormatterRegistrar : feignFormatterRegistrars) { -
feignFormatterRegistrar.registerFormatters(conversionService); -
} -
return conversionService; -
} -
@Configuration -
@ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class }) -
protected static class HystrixFeignConfiguration { -
@Bean -
@Scope("prototype") -
@ConditionalOnMissingBean -
@ConditionalOnProperty(name = "feign.hystrix.enabled", matchIfMissing = false) -
public Feign.Builder feignHystrixBuilder() { -
return HystrixFeign.builder(); -
} -
} -
@Bean -
@ConditionalOnMissingBean -
public Retryer feignRetryer() { -
return Retryer.NEVER_RETRY; -
} -
@Bean -
@Scope("prototype") -
@ConditionalOnMissingBean -
public Feign.Builder feignBuilder(Retryer retryer) { -
return Feign.builder().retryer(retryer); -
} -
@Bean -
@ConditionalOnMissingBean(FeignLoggerFactory.class) -
public FeignLoggerFactory feignLoggerFactory() { -
return new DefaultFeignLoggerFactory(logger); -
} -
}
这两个地方都默认关闭了hystrix,@ConditionalOnProperty(name = "feign.hystrix.enabled", matchIfMissing = false),实际两个都一起工作,这个有待后续研究
本文依然是参考http://blog.didispace.com/springcloud3/,再加上自己翻阅官网源码。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yehuang_0801/article/details/72367096