Hystrix针对不可用服务的保护机制以及引入缓存
之前我写过一篇博文,通过案例了解Hystrix的各种基本使用方式,在这篇文章里,我们是通过Hystrix调用正常工作的服务,也就是说,Hytrix的保护机制并没有起作用,这里我们将在HystrixProtectDemo.java里演示调用不可用的服务时,hystrix启动保护机制的流程。这个类是基于NormalHystrixDemo.java改写的,只是在其中增加了getFallback方法,代码如下。
1 //省略必要的package和import代码
2 public class HystrixProtectDemo extends HystrixCommand<String> {
3 RestClient client = null;
4 HttpRequest request = null;
5 //构造函数很相似
6 public HystrixDemoProtectDemo() {
7 super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
8 }
9 //initRestClient方法没变
10 private void initRestClient(){
11 //和NormalHystrixDemo.java一样,具体请参考代码
12 }
13 //run方法也没变
14 protected String run() {
15 //和NormalHystrixDemo.java一样,具体请参考代码
16 }
17 //这次多个了getFallback方法,一旦出错,会调用其中的代码
18 protected String getFallback() {
19 //省略跳转到错误提示页面的动作
20 return "Call Unavailable Service.";
21 }
22 //main函数
23 public static void main(String[] args) {
24 HystrixDemoProtectDemo normalDemo = new HystrixDemoProtectDemo();
25 normalDemo.initRestClient();
26 try {
27 Thread.sleep(1000);
28 } catch (InterruptedException e) {
29 e.printStackTrace();
30 }
31 String result = normalDemo.execute();
32 System.out.println("Call available function, result is:" + result);
33 }
34 }
这个类里的构造函数和NormalHystrixDemo.java很相似,而initRestClient和run方法根本没变,所以就不再详细给出了。
在第18行里,我们重写了HystrixCommand类的getFallback方法,在其中定义了一旦访问出错的动作,这里仅仅是输出一段话,在实际的项目里,可以跳转到相应的错误提示页面。
而main函数里的代码和NormalHystrixDemo.java里的完全一样,只是,在运行这段代码前无需运行HystrixServerDemo项目的启动类,这样服务一定是调用不到的。运行本段代码后,我们能看到如下的结果。
In run
Call available function, result is:Call Unavailable Service.
从第2行的输出上,我们能确认,一旦调用服务出错,Hystrix处理类能自动地调用getFallback方法。
如果这里没有定义getFallback方法,那么一旦服务不可用,那么用户可能在连接超时之后,在浏览器里看到一串毫无意义的内容,这样用户体验就很差,如果整个系统的其它容错措施也没到位,甚至就有可能导致当前和下游模块瘫痪。
相反,在这里由于我们在hystirx提供的getFallback方法里做了充分的准备,那么一旦出现错误,这段错误处理的代码能被立即触发,其效果就相当于熔断后继的处理流程。
由getFallback出面,友好地告知用户出问题了,以及后继该如何处理,这样一方面能及时熔断请求从而保护整个系统,另一方面不会造成因体验过差而用户大规模流失的情况。
如果每次请求都要走后台应用程序乃至再到数据库检索一下数据,这对服务器的压力太大,有时候这一因素甚至会成为影响网站服务性能的瓶颈。所以,大多数网站会把一些无需实时更新的数据放入缓存,前端请求是到缓存里拿数据。
Hystrix在提供保护性便利的同时,也能支持缓存的功能,在下面的HystrixCacheDemo.java里,我们将演示Hystrix从缓存中读取数据的步骤,代码如下。
1 //省略必要的package和import代码
2 public class HystrixCacheDemo extends HystrixCommand<String> {
3 //用户id
4 Integer id;
5 //用一个HashMap来模拟数据库里的数据
6 private HashMap<Integer,String> userList = new HashMap<Integer,String>();
7 //构造函数
8 public HystrixCacheDemo(Integer id) {
9 super(HystrixCommandGroupKey.Factory.asKey("RequestCacheCommand"));
10 this.id = id;
11 userList.put(1, "Tom");
12 }
在第3行里,我们定义了一个用户id,并在第6行定义了一个存放用户信息的HashMap。
在第8行的构造函数里,我们在第10行里用参数id来初始化了本对象的id属性,并在第11行里,通过put方法模拟地构建了一个用户,在项目里,用户的信息其实是存在数据库里的。
13 protected String run() {
14 System.out.println("In run");
15 return userList.get(id);
16 }
如果不走缓存的话,第13行定义run函数将会被execute方法触发,在其中的第15行里,我们通过get方法从userList这个HashMap里获得一条用户数据,这里我们用get方法来模拟根据id从数据库里获取数据的诸多动作。
17 protected String getCacheKey() {
18 return String.valueOf(id);
19 }
第17行定义的getCacheKey方法是Hystrix实现缓存的关键,在其中我们可以定义“缓存对象的标准”,具体而言,我们在这里是返回String.valueOf(id),也就是说,如果第二个HystrixCacheDemo对象和第一个对象具有相同的String.valueOf(id)的值,那么第二个对象在调用execute方法时,就可以走缓存。
public static void main(String[] args) {
21 //初始化上下文,否则无法用缓存机制
22 HystrixRequestContext context = HystrixRequestContext.initializeContext();
23 //定义两个具有相同id的对象
24 HystrixCacheDemo cacheDemo1 = new HystrixCacheDemo(1);
25 HystrixCacheDemo cacheDemo2 = new HystrixCacheDemo(1);
26 //第一个对象调用的是run方法,没有走缓存
27 System.out.println("the result for cacheDemo1 is:" + cacheDemo1.execute());
28 System.out.println("whether get from cache:" + cacheDemo1.isResponseFromCache);
29 //第二个对象,由于和第一个对象具有相同的id,所以走缓存
30 System.out.println("the result for cacheDemo2 is:" + cacheDemo2.execute());
31 System.out.println("whether get from cache:" + cacheDemo2.isResponseFromCache);
32 //销魂上下文,以清空缓存
33 context.shutdown();
34 //再次初始化上下文,但由于缓存已清,所以cacheDemo3没走缓存
35 context = HystrixRequestContext.initializeContext();
36 HystrixCacheDemo cacheDemo3 = new HystrixCacheDemo(1);
37 System.out.println("the result for 3 is:" + cacheDemo3.execute());
38 System.out.println("whether get from cache:" + cacheDemo3.isResponseFromCache);
39 context.shutdown();
在第20行的main方法里,我们定义了如下的主要逻辑。
第一,在第22行,通过initializeContext方法,初始化了上下文,这样才能启动缓存机制。,在第24和25行里,我们创建了两个不同名的,但相同id的HystrixCacheDemo对象。
第二,在第27行里,我们通过cacheDemo1对象的execute方法,根据id查找用户,虽然我们在这里是通过run方法里第15行的get方法从HashMap里取数据,但大家可以把这想象成从数据表里取数据。
第三,在第30行里,我们调用了cacheDemo2对象的execute方法,由于它和cacheDemo1对象具有相同的id,所以这里并没有走execute方法,而是直接从保存cacheDemo1.execute的缓存里拿数据,这就可以避免因多次访问数据库而造成了系统损耗。
第四,我们在第33行销毁了上下文,并在第35行里重新初始化了上下文,之后,虽然在第36行定义的cacheDemo3对象的id依然是1,但由于上下文对象被重置过,其中的缓存也被清空,所以在第37里执行的execute方法并没有走缓存。
运行上述代码,我们能看到如下的输出,这些打印结果能很好地验证上述对主要流程的说明。
1 In run
2 the result for cacheDemo1 is:Tom
3 whether get from cache:false
4 the result for cacheDemo2 is:Tom
5 whether get from cache:true
6 In run
7 the result for 3 is:Tom
这里请大家注意,在缓存相关的getCacheKey方法里,我们不是定义“保存缓存值”的逻辑,而是定义“缓存对象的标准”,初学者经常会混淆这点。具体而言,在这里的getCacheKey方法里,我们并没有保存id是1的User对象的值(这里是Tom),而是定义了如下的标准:只要两个(或多个)HystrixCacheDemo对象具有相同的String.valueOf(id)的值,而且缓存中也已经存有id的1的结果值,那么后继对象则可以直接从缓存里读数据。
在上文里,我们演示了通过Hystrix调用可用以及不可用服务的运行结果,并在调用过程中引入了缓存机制,这里,我们将在上述案例的基础上归纳Hystrix的一般工作流程。
第一,我们可以通过extends HystrixCommand<T>的方式,让一个类具备Hystrix保护机制的特性,其中T是泛型,在上述案例中我们用到的是String。
第二,一旦继承了HystrixCommand之后,我们就可以通过重写run方法和getFallback方法来定义调用“可用”和“不可用”服务的业务功能代码,其中,这两个方法的返回值需要和第一步里定义的泛型T一致。而在项目里,我们一般在getFallback方法里,定义“服务不可用”时的保护措施(也就是后文里将要提到的降级措施)。
第三,我们还可以通过缓存机制来降低并发情况下对服务器的压力,在Hystrix里,我们可以在getCacheKey里定义“判断可以走缓存对象的标准”。
在使用缓存是,请注意两点,第一需要开启上下文,第二,Hystrix会根据定义在类里的属性判断多次调用的对象是否是同一个,如果是,而且之前被调用过,则可以走缓存。
本文谢绝转载。
Hystrix针对不可用服务的保护机制以及引入缓存的更多相关文章
- 用 Hystrix 构建高可用服务架构
1 hystrix是什么 在分布式系统中,每个服务都可能会调用很多其他服务,被调用的那些服务就是依赖服务,有的时候某些依赖服务出现故障也是很正常的. Hystrix 可以让我们在分布式系统中对服务间的 ...
- spring cloud 入门系列四:使用Hystrix 实现断路器进行服务容错保护
在微服务中,我们将系统拆分为很多个服务单元,各单元之间通过服务注册和订阅消费的方式进行相互依赖.但是如果有一些服务出现问题了会怎么样? 比如说有三个服务(ABC),A调用B,B调用C.由于网络延迟或C ...
- SpringCould-------使用Hystrix 实现断路器进行服务容错保护
消费: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.or ...
- 白话SpringCloud | 第五章:服务容错保护(Hystrix)
前言 前一章节,我们知道了如何利用RestTemplate+Ribbon和Feign的方式进行服务的调用.在微服务架构中,一个服务可能会调用很多的其他微服务应用,虽然做了多集群部署,但可能还会存在诸如 ...
- 第五章 服务容错保护:Spring Cloud Hystrix
在微服务架构中,我们将系统拆分为很多个服务,各个服务之间通过注册与订阅的方式相互依赖,由于各个服务都是在各自的进程中运行,就有可能由于网络原因或者服务自身的问题导致调用故障或延迟,随着服务的积压,可能 ...
- Spring Cloud(四):服务容错保护 Hystrix【Finchley 版】
Spring Cloud(四):服务容错保护 Hystrix[Finchley 版] 发表于 2018-04-15 | 更新于 2018-05-07 | 分布式系统中经常会出现某个基础服务不可用 ...
- Spring Cloud Hystrix 服务容错保护
目录 一.Hystrix 是什么 二.Hystrix断路器搭建 三.断路器优化 一.Hystrix 是什么 在微服务架构中,我们将系统拆分成了若干弱小的单元,单元与单元之间通过HTTP或者TCP等 ...
- 笔记:Spring Cloud Hystrix 服务容错保护
由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加 ...
- 《springcloud 四》服务保护机制
服务保护机制SpringCloud Hystrix 微服务高可用技术 大型复杂的分布式系统中,高可用相关的技术架构非常重要. 高可用架构非常重要的一个环节,就是如何将分布式系统中的各个服务打造成高可用 ...
随机推荐
- 使用Fiddler完成Android和IOS手机抓包Https
实现原理 Fiddler是PC端有名的HTTP抓包工具,利用它我们可以轻松实现对主机上所有http/https网络请求的捕捉.查看和修改操作. 同时它也提供了代理模式,其它主机由它代理发送的网络请求也 ...
- python tesserocr ImportError: dll loading failed 一个不常遇见的错误,以及简单的python安装方法~
废话不多说了,这是写给小白的了. 本人有c#,c/c++开发经验,最近因为偶然的原因,开始接触python,遇到一个棘手的问题,一位朋友在安装tesserocr 包后遇到一个错误,重新安装数次不能解决 ...
- Windows 运行命令大全,装逼必备哦!
以下已整理,以字母先后排序: appwiz.cpl:程序和功能 cliconfg:SQL SERVER 客户端网络实用工具 cmd:CMD命令提示符 comexp.msc或者dcomcnfg:组件服务 ...
- Java中 StringTokenizer 的用法
一.StringTokenizer 1.1 StringTokenizer简介及其构造函数的三种形式: StringTokenizer类是字符串分割解析类型,其属于java.util包,在使用之前需要 ...
- CentOS Linux搭建SVN服务器
Linux系统:CentOS 安装步骤如下: 1.yum install subversion 2.输入rpm -ql subversion查看安装位置,如下图: 可以看到 svn在bin目录下生成了 ...
- BZOJ5304 : [Haoi2018]字串覆盖
离线处理所有询问. 对于$r-l\leq 50$的情况: 按照串长从$1$到$51$分别把所有子串按照第一位字符为第一关键字,上一次排序结果为第二关键字进行$O(n)$基数排序. 同理也可以用上一次比 ...
- 线段树模板1 [Luogu P3372]
代码+注释: #include <iostream> #include <cstdio> using namespace std; int n, q, flag, x, y, ...
- Windows10用fiddler抓包Android应用(解决手机设置代理后无法上网,设置只抓app包)
1.环境准备 1.电脑上安装fiddler 2.手机和电脑在同一个局域网内 2.设置 1.fiddler>Tools>Fiddler Options>Connections 勾选Al ...
- 用JDBC把Excel中的数据导入到Mysql数据库中
步骤:0.在Mysql数据库中先建好table 1.从Excel表格读数据 2.用JDBC连接Mysql数据库 3.把读出的数据导入到Mysql数据库的相应表中 其中,步骤0的table我是先在Mys ...
- pytroch nn.Module源码解析(1)
今天在写一个分类网络时,要使用nn.Sequential中的一个模块,因为nn.Sequential中模块都没有名字,我一时竟无从下笔.于是决定写这篇博客梳理pytorch的nn.Module类,看完 ...