我是靠谱客的博主 仁爱棒棒糖,最近开发中收集的这篇文章主要介绍微服务之三:Hystrix(2)一: 整合Hystrix1.1概述1.2 服务调用者添加依赖(invoker)1.3 新建服务类,在服务方法中调用服务1.3 控制层1.4 更改启动类二: 配置2.3 缓存注解三:Feign与Hystrix整合,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
spring cloud中使用Hystrix
- 一: 整合Hystrix
- 1.1概述
- 1.2 服务调用者添加依赖(invoker)
- 1.3 新建服务类,在服务方法中调用服务
- 1.3 控制层
- 1.4 更改启动类
- 二: 配置
- 2.1 一般配置
- 2.2 全局配置
- 2.3 缓存注解
- 2.3.1 拦截器
- 2.3.2 启动类
- 2.3.3 服务层
- 2.3.4 控制层
- 2.4 删除缓存
- 三:Feign与Hystrix整合
- 3.0 服务提供者(provider)
- 3.1 服务调用者添加依赖(invoker)
- 3.2 application.yml文件配置(invoker)
- 3.3 修改启动类,添加注解(invoker)
- 3.4 创建访问接口(invoker)
- 3.5 执行回退类(invoker)
- 3.6 控制类(invoker)
- 3.7 服务调用者(invoker)
一: 整合Hystrix
1.1概述
Hystrix主要用于保护调用服务的一方,如果被调用的服务发生故障,符合一定条件,就开启短路器,对调用的程序进行隔离
项目准备:
- spring -Hystrix-service:Eureka服务器。8761
- spring-Hystrix-provider:服务提供者,8080
- /hello/{personId}
- /hello
- spring-hystrix-invoker:服务调用者
1.2 服务调用者添加依赖(invoker)
<!-- Hystrix依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
1.3 新建服务类,在服务方法中调用服务
package com.atm.cloud;
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;
@Service
public class PersonService {
@Autowired
RestTemplate restTemplate;
//使用Hystrix的注解,当服务提供者不启动时,直接直接回退方法
@HystrixCommand(fallbackMethod = "findPersonFallback")
public Person findPerson(Integer personId) {
Person person = restTemplate.getForObject(
"http://atm-eureka-hystrix-provider/person/{personId}",
Person.class, personId);
return person;
}
// fallBack方法需要和findPerson的参数一致
public Person findPersonFallback(Integer personId) {
Person p = new Person();
p.setId(10);
p.setAge(personId);
p.setName("i am fallback!");
return p;
}
}
1.3 控制层
package com.atm.cloud;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Configuration
public class MyRouterController {
@Autowired
private PersonService personService;
@RequestMapping(value = "/router", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Person router() {
return personService.findPerson(2);
}
}
1.4 更改启动类
在启动类中加入启动断路器的注解
package com.atm.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker//打开断路器
public class HystrixInvokerApp {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(HystrixInvokerApp.class, args);
}
}
注:
服务类注入了RestTemplate,服务方法使用@HystrixCommand注解进行修饰,并且配置了回退方法。
二: 配置
- 一般配置(针对单个方法进行配置)
- 默认配置(针对整个类进行配置)
2.1 一般配置
/**
*
commandKey:之前用作缓存 ,
*
groupKey:用于执行线程,
*
重要的是超时时间的配置,
*
线程池的配置
*/
@HystrixCommand(
fallbackMethod = "findPersonFallback",
groupKey = "PersonGroupKey",
commandKey = "PersonCommandKey",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
},
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "2")
})
public Person findPerson(Integer personId) {
Person person = restTemplate.getForObject(
"http://atm-eureka-hystrix-provider/person/{personId}",
Person.class, personId);
return person;
}
2.2 全局配置
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
@Service
@DefaultProperties(defaultFallback = "findPersonFallback")
public class PersonService {
}
// 默认的回退方法,是没有参数的
public Person findPersonFallback() {
Person p = new Person();
p.setId(10);
p.setAge(1);
p.setName("i am fallback!");
return p;
}
2.3 缓存注解
- 新建过滤器
- 使用缓存注解
- 多次同一请求(同一请求中调用同样的资源),可考虑使用缓存
缓存与合并请求功能需要先初始化请求上下文才能实现,所以需要新建一个拦截器,拦截所有的访问路
2.3.1 拦截器
package com.atm.cloud.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
/*
* 需要配置一下:让Spring容器知道这个Filter我们需要用到
*
* urlPatterns="/*",拦截全部请求
*
* filterName="hystrixFilter",过滤器名称
*/
@WebFilter(urlPatterns = "/*", filterName = "hystrixFilter")
public class MyFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 对每一个请求进行拦截,拦截之后干什么呢?
System.out.println("开始执行过滤器....");
HystrixRequestContext ctx = HystrixRequestContext.initializeContext();
try {
chain.doFilter(request, response);
} catch (Exception e) {
} finally {
ctx.shutdown();
}
}
public void init(FilterConfig config) throws ServletException {
}
}
上述代码中,最重要的是 HystrixRequestContext ctx = HystrixRequestContext.initializeContext(); 初始化启动上下
2.3.2 启动类
package com.atm.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
// 打开断路器
@EnableCircuitBreaker
// 扫描
@ServletComponentScan
public class HystrixInvokerApp {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(HystrixInvokerApp.class, args);
}
}
2.3.3 服务层
package com.atm.cloud.cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.atm.cloud.Person;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
@Service
public class CacheService {
@Autowired
RestTemplate restTemplate;
// @CacheResult需要配合@HystrixCommand一起使用
@CacheResult
@HystrixCommand
public Person cachePerson(Integer personId) {
System.out.println("调用CachePerson()...");
return null;
}
}
2.3.4 控制层
package com.atm.cloud.cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.atm.cloud.Person;
@RestController
public class CacheController {
@Autowired
private CacheService cacheService;
@RequestMapping(value = "/cache", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public String router() {
for (int i = 0; i < 5; i++) {
cacheService.cachePerson(1);
}
return "访问成功";
}
}
访问控制层的接口可以看出,服务方法只调用了一次,其他次都是直接从缓存中获取的。
缓存的注解主要有以下三个:
- @CacheResult:该注解修饰方法,表示被注释的方法返回结果将会被缓存,但是余下和@HystrixConmmand一起使用
- @CacheRemove:用于修饰方法,让缓存失效,需要与CacheResult的缓存Key关联
- CacheKey:用于修饰方法参数,表示该缓存作为缓存的key
2.4 删除缓存
- 配置命令key
- 使用注解删除缓存
@Service
public class CacheService {
// 调用这个方法将设置缓存
@CacheResult
@HystrixCommand(commandKey = "cacheKey")
public String getCache(Integer id) {
System.out.println("查询缓存()....");
return "";
}
// 调用这个方法将设清除缓存
@CacheRemove(commandKey = "cacheKey")
@HystrixCommand
public String removePerson(Integer id) {
System.out.println("删除()....");
return "";
}
}
三:Feign与Hystrix整合
Feign对Hystrix提供了支持,编写接口和实现依赖
3.0 服务提供者(provider)
package com.atm.cloud;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyRestController {
@GetMapping("/tmhello")
@ResponseBody
public String timeOutHello() throws InterruptedException {
// 此方法处理最少需要1s
Thread.sleep(1000);
return "TimeOut Hello";
}
}
3.1 服务调用者添加依赖(invoker)
<!-- Feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
3.2 application.yml文件配置(invoker)
- 开启Feign开关
server:
port: 9000
spring:
application:
name: atm-eureka-hystrix-invoker
feign:
hystrix:
enabled: true
hystrix:
command:
##全局方法使用default
HelloClient#toHello():
execution:
isolation:
thread:
##超时时间
timeoutInMilliseconds: 500
circuitBreaker:
##每秒3次请求
requestVolumeThreshold: 3
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
3.3 修改启动类,添加注解(invoker)
package com.atm.cloud;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker//打开Hystrix断路器
@ServletComponentScan//扫描缓存
@EnableFeignClients//打开Feign注解
public class HystrixInvokerApp {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
new SpringApplicationBuilder(HystrixInvokerApp.class).web(true).run(
args);
}
}
3.4 创建访问接口(invoker)
package com.atm.cloud.feignCtr;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
//当HellClien访问atm-eureka-hystrix-provider失败时,需要有一个后备服务
//后备服务需要实现该接口
@FeignClient(name = "atm-eureka-hystrix-provider", fallback = HelloClientFallBack.class)
public interface HelloClient {
@RequestMapping(method = RequestMethod.GET, value = "/tmhello")
String toHello();
}
3.5 执行回退类(invoker)
package com.atm.cloud.feignCtr;
import org.springframework.stereotype.Component;
@Component
public class HelloClientFallBack implements HelloClient {
public String toHello() {
return "fallBack timeOut Hello";
}
}
3.6 控制类(invoker)
package com.atm.cloud.feignCtr;
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 com.netflix.hystrix.HystrixCircuitBreaker;
import com.netflix.hystrix.HystrixCommandKey;
@RestController
public class FeignController {
@Autowired
private HelloClient helloClient;
@RequestMapping(value = "tmHello", method = RequestMethod.GET)
public String tmHello() {
String result = helloClient.toHello();
HystrixCircuitBreaker breaker = HystrixCircuitBreaker.Factory
.getInstance(HystrixCommandKey.Factory
.asKey("HelloClient#toHello()"));
System.out.println("断路器状态:" + breaker.isOpen());
return result;
}
}
3.7 服务调用者(invoker)
package com.atm.cloud.feignCtr;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class HttpClientMain {
public static void main(String[] args) throws Exception{
final CloseableHttpClient httpclient = HttpClients.createDefault();
final String url = "http://localhost:9000/tmHello";
for(int i = 0; i < 6; i++) {
Thread t = new Thread() {
@Override
public void run() {
try {
HttpGet httpget = new HttpGet(url);
HttpResponse response = httpclient.execute(httpget);
System.out.println(EntityUtils.toString(response.getEntity()));
} catch (Exception e ) {
e.printStackTrace();
}
}
};
t.start();
}
Thread.sleep(15000);
}
}
最后
以上就是仁爱棒棒糖为你收集整理的微服务之三:Hystrix(2)一: 整合Hystrix1.1概述1.2 服务调用者添加依赖(invoker)1.3 新建服务类,在服务方法中调用服务1.3 控制层1.4 更改启动类二: 配置2.3 缓存注解三:Feign与Hystrix整合的全部内容,希望文章能够帮你解决微服务之三:Hystrix(2)一: 整合Hystrix1.1概述1.2 服务调用者添加依赖(invoker)1.3 新建服务类,在服务方法中调用服务1.3 控制层1.4 更改启动类二: 配置2.3 缓存注解三:Feign与Hystrix整合所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复