我是靠谱客的博主 仁爱棒棒糖,这篇文章主要介绍微服务之三: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)

复制代码
1
2
3
4
5
6
<!-- Hystrix依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>

1.3 新建服务类,在服务方法中调用服务

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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 控制层

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 更改启动类

在启动类中加入启动断路器的注解

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 一般配置

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/** * 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 全局配置

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 拦截器

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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 启动类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 服务层

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 控制层

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
  • 使用注解删除缓存
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@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)

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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)

复制代码
1
2
3
4
5
6
<!-- Feign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>

3.2 application.yml文件配置(invoker)

  • 开启Feign开关
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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)

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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)

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
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)

复制代码
1
2
3
4
5
6
7
8
9
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)

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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)

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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)一:内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(63)

评论列表共有 0 条评论

立即
投稿
返回
顶部