这段时间接了个需求,需要在我目前负责的数据系统上加个接口,主要是实现用户行为的记录。前端对接的项目主要有公司的PC,WAP,WEIXIN,APP等,每个端大概有两台左右的负载。因为目前我的这个项目主要是面向内部,负责数据运营相关的内容,是个单体项目。如果线上各个接入点不做限制,瞬间大量的并发进入必然会导致目前项目的崩溃,其他的功能也无法正常使用。

1、需求分析

通过前期的需求分析,目前线上系统无法进行限流处理,所以最终解决问题还是要从接口入手。

目前我对接口的处理有两种实现方案:

  1. 可以利用MQ实现消息的错峰,将消息发送到MQ服务器。
  2. 实现对接口的隔离限流,避免当前接口对其他功能的影响。

其实我认为最好的实现方案就是第一种了,可以保证消息的准确送达,避免并发资源的占用。不过,因为公司条件的限制暂时不能新增中间件,所以只能在现有系统上进行改造,最后只能采用第二种方法了。

2、Hystrix的简单介绍

官方的定义就不说了,这里简单说下我的理解。Hystrix作为断路器主要是实现对服务的容错保护,简单来说就是服务隔离、服务降级、服务熔断,服务限流这几项。

举个常见的例子,当你某宝【抢购】一个产品时,经常会弹出[网络错误,请重试。]的提示,这种时候是真的网络问题吗?显示不是。这种情况下其实是对调用的接口进行了降级处理,当降级的次数或比例达到一定的条件后,断路器就会直接打开,之后的访问就会直接降级,而不会判断是否降级了。达到对服务的容错保护以及给用户友好提示的目的。详细的流程可以看下图。

一般Hystrix的容错保护在微服务中是用在客户端,也就是调用方。而我这次实际上是用在了提供方,主要是前台的项目我无法控制,只能在接口上想方法了。目前我使用Hystrix的主要目的就是实现对服务的隔离和限流,而对降级和熔断反而不是特别的关心,当然实际的使用要结合场景。

因为一般Tomcat默认是一个线程池150个线程,如果单个热点接口的请求过多,就会造成其他功能没有线程可用甚至直接程序崩溃的问题。Hystrix的服务隔离主要有两种,常用的就是线程池隔离的方式,对热点接口建立单独的线程池避免对主程序的影响。另一种是信号量的方式,用的场景不是太多。两者的区别其实就是一个增大系统的开销,一个则直接限制了线程总的并发数,开销更小一些。

Hystrix服务调用逻辑图

3、项目中的应用实现

本文是在传统Spring项目中的应用,Springboot中的相关配置和依赖有稍许的不同。

maven依赖:

     <!-- hystrix -->
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>1.5.9</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-metrics-event-stream</artifactId>
<version>1.5.9</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-javanica</artifactId>
<version>1.5.9</version>
</dependency>

在Spring的配置文件中配置Hystrix的切面信息

    <bean id="hystrixAspect" class="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"></bean>
<aop:aspectj-autoproxy />

主要是开启注解的AOP扫描,这里我们可以在这个类的源码中看到实现

可以看到我们主要是通过这个类切面扫描Hystrix的相关注解,以达到接口处理前,提前执行Hystrix相关逻辑的代码。

/**
* 提供客户行为接口
*
*/
@Controller
@RequestMapping(value = "/test")
public class BehaviorController {
Logger logger = Logger.getLogger(BehaviorController.class);
@Autowired
private BehaviorService behaviorService; @RequestMapping(value="/addBehavior",method = RequestMethod.POST,produces = "application/json;charset=UTF-8")
@ResponseBody
@HystrixCommand(fallbackMethod = "fallback", threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "20"), @HystrixProperty(name = "maxQueueSize", value = "100"),
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "20")},
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "30000"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20") })
public String addBehavior(@RequestBody String parms) { //业务逻辑实现
return result;
} public String fallback(@RequestBody String parms){
logger.info("fallback");
//失败的实现
return result;
}
}

注意:
请求的接口必须为public,fallback为降级的接口逻辑,可以为private,也可以为public。

但是要特别注意fallback方法的返回值和参数必须和请求方法相同

另外需要说的是,当请求失败、被拒绝、超时或者断路器打开时,都会进入回退方法,但是进入回退方法并不意味着断路器已经被打开。

4、常用参数的介绍

参数

描述

默认值

execution.isolation.strategy

隔离策略,有THREAD和SEMAPHORE

THREAD - 它在单独的线程上执行,并发请求受线程池中的线程数量的限制
SEMAPHORE - 它在调用线程上执行,并发请求受到信号量计数的限制

默认使用THREAD模式,以下几种场景可以使用SEMAPHORE模式:

只想控制并发度

外部的方法已经做了线程隔离

调用的是本地方法或者可靠度非常高、耗时特别小的方法(如medis)

execution.isolation.thread.timeoutInMilliseconds

超时时间

默认值:1000

在THREAD模式下,达到超时时间,可以中断

在SEMAPHORE模式下,会等待执行完成后,再去判断是否超时

设置标准:

有retry,99meantime+avg meantime

没有retry,99.5meantime

execution.timeout.enabled

HystrixCommand.run()执行是否应该有超时。

默认值:true

fallback.isolation.semaphore.maxConcurrentRequests

设置在使用时允许执行fallback方法的最大并发请求数

默认值:10

circuitBreaker.requestVolumeThreshold

设置滚动时间窗中,断路器熔断的最小请求数

默认值:20

滚动窗口默认10s,即10s内失败请求达到20个,熔断器即打开

coreSize

设置执行命令线程池的核心线程数。

默认值:10

maxQueueSize

设置执行命令线程池的核心线程数。

默认值:-1

当设置为-1时,线程池使用SynchronousQueue实现的队列,否则将使用LinkedBlockingQueue实现的队列

queueSizeRejectionThreshold

为队列设置拒绝阈值

默认值:5

当设置该参数后,即使队列没有达到最大值也能拒绝请求。

注意:当maxQueueSize属性为-1的时候,该属性不会生效

另外需要特别注意的是:fallback的属性maxConcurrentRequests,当请求达到了最大并发数时,后续的请求将会被拒绝并抛出异常(因为它已经没有后续的fallback可以被调用了),异常信息一般为com.netflix.hystrix.exception.HystrixRuntimeException: xxxxxxx fallback execution rejected.

更多参数见官方文档:https://github.com/Netflix/Hystrix/wiki/Configuration

另外附一个网友翻译的文档:https://blog.csdn.net/tongtong_use/article/details/78611225

5、接口测试

并发接口测试的方法很多,可以写代码,也可以用apache batch以及jmeter等工具。以常用的jmeter为例,测试本接口。

设置环境变量:
JMETER_HOME D:\apache-jmeter-3.0
CLASSPATH %JMETER_HOME%\lib\ext\ApacheJMeter_core.jar;%JMETER_HOME%\lib\jorphan.jar;%JMETER_HOME%\lib/logkit-2.0.jar;

新建线程组:

设置并发参数:

第一个参数为线程数,第二个参数为启动时间,第三个参数为请求次数。以上述配置为例即为1秒内启动50个线程,每个线程请求一次。

添加HTTP请求

这里设置请求的路径,参数等等。

设置请求头信息,因人而异

我的设置:Content-Type:application/json

表格查看结果

查看结果:

这个可以根据机器的性能进行测试,以我的接口为例,当设置并发数为100以内时,基本上不会有降级处理,当并发数大于100时,就会有部分请求进入降级接口了。

6、接口监控

实际项目中,经常需要对我们的接口和项目情况进行监控,Hystrix已经为我们考虑到了。Hystrix提供了近乎实时的监控,Hystrix会实时的,累加的记录所有关于HystrixCommand的执行信息,包括执行了每秒执行了多少请求,多少成功,多少失败等等,更多指标请查看:https://github.com/Netflix/Hystrix/wiki/Metrics-and-Monitoring

在web.xml中添加下述配置:

    <!-- for Hystrix -->
<servlet>
<display-name>HystrixMetricsStreamServlet</display-name>
<servlet-name>HystrixMetricsStreamServlet</servlet-name>
<servlet-class>com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>HystrixMetricsStreamServlet</servlet-name>
<url-pattern>/hystrix.stream</url-pattern>
</servlet-mapping>

启动应用。访问http://hostname:port/项目名/hystrix.stream,可以看到下面信息

这种是最原生的监控使用方式,大家可以另外集成Hystrix 提供的一个 Dashboard 应用。Dashboard 是一个单独的应用,我们可以独立部署。如果需要监控整个 Hystrix 集群,就需要使用 Turbine 应用。Turbine 也是 Netflix 开源的一个服务。但是使用 Hystrix Stream 和 Turbine 存在一个明显的不足,那就是无法查看历史的监控数据。解决这个问题就需要我们自己来实现了。

监控的相关不是本文的重点,就不多介绍了,大家可以百度下hystrix在微服务项目中监控的实现,这里网上文章很多,基本上和传统项目没有任何区别了,大家可以参考实现。

传统项目利用Hystrix实现热点接口的服务隔离的更多相关文章

  1. springboot项目利用Swagger2生成在线接口文档

    Swagger简介. Swagger2是一款restful接口文档在线生成和在线调试工具.很多项目团队利用Swagger自动生成接口文档,保证接口文档和代码同步更新.在线调试.简单地说,你可以利用这个 ...

  2. Spring Cloud实战之初级入门(四)— 利用Hystrix实现服务熔断与服务监控

    目录 1.环境介绍 2.服务监控 2.1 加入依赖 2.2 修改配置文件 2.3 修改启动文件 2.4 监控服务 2.5 小结 3. 利用hystrix实现消费服务熔断 3.1 加入服务熔断 3.2 ...

  3. Dubbo 项目与传统项目

    1.什么是传统工程 单工程 MVC 架构 控制层通过调用服务层完成业务逻辑处理 业务层调用持久层进程数据操作 2.什么是分布式工程 将传统项目的单工程结构,拆分成多工程 一般会有这几个工程: 父工程: ...

  4. SpringBoot项目集成Hystrix

    Hystrix Hystrix是由Netflix开源的一个服务隔离组件,通过服务隔离来避免由于依赖延迟.异常,引起资源耗尽导致系统不可用的解决方案. 1.什么是服务熔断   服务熔断就是对该服务的调用 ...

  5. 利用python3 调用zabbix接口完成批量加聚合图形(screens)

    在上一篇博客中,我们完成的利用python3 调用zabbix接口批量增加主机,增加主机的item,增加主机的图形! 接下来我们完成批量增加主机的screen 首先我们要增加screen需要哪些参数呢 ...

  6. Winform项目调用asp.net数据接口

    最近一个WPF项目需要改写成android项目,思路是在asp.net项目中编写一个通用接口,便于其它平台下调用数据.刚接触到这些东西的时候完全是一头雾水,最根本的原因是不明白网站中的一个网页,为什么 ...

  7. 若依项目利用nginx实现负载均衡及保持会话

    记录一下若依项目利用nginx实现负载均衡及保持会话的步骤. 此次作为试验性的测试,为了方便在本地window的环境上实现. 具体步骤: 1.安装两个tomcat8,可以下载一个后,另一个复制即可,下 ...

  8. 关于传统项目打成war包的的分析

    技术在不断的革新,以前的项目没有jar管理工具时,都是手动将依赖的jar拷贝到项目之下,然后Build Path,之后Maven出现了,出现了jar包中央仓库,所有的jar包资源集中在这里,免去频繁去 ...

  9. laravel项目利用twemproxy部署redis集群的完整步骤

    Twemproxy是一个代理服务器,可以通过它减少Memcached或Redis服务器所打开的连接数.下面这篇文章主要给大家介绍了关于laravel项目利用twemproxy部署redis集群的相关资 ...

随机推荐

  1. 《WAP》第一次作业:团队亮相

    一.队名:WAP! 二.团队成员组长 组员 : 201571030302/杜有海 201571030327/乌勒扎 201571030304/郝明宇 201571030318/马麒 组长: 20157 ...

  2. JVM虚拟机调优指南

    本章通过阅读JVM垃圾搜集指南文档,整理虚拟机主要配置以及,理解不同的垃圾搜集器. 垃圾搜集算法 引用计数算法 根搜索算法 标记-清除算法 复制算法 标记-整理算法 分代收集算法 搜集算法网上有很多介 ...

  3. Rails 5 Test Prescriptions(everday Rspectest作者推荐) 目录 1-3章

    总文档连接: RSpec.info/documentation/ 如何使用TDD 和 自动化测试来建立一个Rails app. TDD让你用测试来探索代码的设计.你将学习可利用的工具,并学习用什么工具 ...

  4. VS中的生成事件

    1:为什么需要使用生成事件? 在实际开发过程中,一个公共使用的类库,在项目生成DLL后需要被复制到不同的目录下被引用,是不是觉得每次生成之后都需要人工复制是很麻烦的一件事情 我们可以利用VS中的项目生 ...

  5. VS2013命令行界面查看虚函数的内存布局

    内存布局可能使用vs的界面调试看到的旺旺是一串数字,很不方便,但是vs的命令行界面可以很直观的显示出一个类中具体的内存布局. 打开命令行.界面如下所示: 测试代码如下所示: class Base1 { ...

  6. SVN的 安装

    关于svn的安装,如图分别是服务端和客户端 下载地址:http://subversion.apache.org/packages.html 1.双击VisualSVN,点下一步,选择目录,就可以,很简 ...

  7. LightOJ - 1396 :Palindromic Numbers (III)(逐位确定法)

    Vinci is a little boy and is very creative. One day his teacher asked him to write all the Palindrom ...

  8. 事务的隔离级别以及oracle中的锁

    事务的概念及特性 事务,一般是指要做的或所做的事情.在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit). 例如:在关系数据库中,一个事务可以是一条SQL语句,一组SQL语 ...

  9. noi.ac上的一套(假)NOI题

    noi.ac上的一套(假)NOI题 本来想着可以刷点通过量的,结果发现好像并不是这样的. 整数 description 给你\(n,p\),要你求\(\sum_{k=1}^n\sum_{i=1}^k\ ...

  10. java编程之常见的排序算法

    java常见的排序算法 第一种:插入排序 直接插入排序 1, 直接插入排序 (1)基本思想:在要排序的一组数中,假设前面(n-1)[n>=2] 个数已经是排 好顺序的,现在要把第n个数插到前面的 ...