Hystrix实例与高并发测试

简介

Hystrix配置中我们简单的了解了Hystrix常用的一些配置,这一篇我们简单的通过一些实例来加深对这些配置的理解。

并且通过ab做一点简单的并发测试,来看一下Hystrix对系统在流量比较高的时候的影响。

模拟服务

import java.util.concurrent.TimeUnit;

public class ServiceMockUtil {

    public static String mock()  {
        double random = Math.random();
        System.out.println(random);
        if(Double.compare(0.2,random) >= 0) {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                return "interrupted";
            }
            return "5";
        }else if(Double.compare(0.2,random) < 0 && Double.compare(0.8,random)>0){
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                return "interrupted";
            }
            return "1";
        }
        return "im";
    }

    public static String mockSixtyFiveSecond()  {
        double random = Math.random();
        System.out.println(random);
        if(Double.compare(0.5,random) >= 0) {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                return "interrupted";
            }
            return "5";
        }
        return "im";
    }
}

先来一个模拟的服务的类,用来模拟服务的调用时间,通过随机的方式让休眠一些时间。

HystrixCommand

import cn.freemethod.service.ServiceMockUtil;
import com.netflix.hystrix.*;

public class LoginHystrixCommand extends HystrixCommand<String>{

    private static Setter getSetter() {
        return Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("groupOne"))
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(Thread.currentThread().getId() + "login"))
                .andCommandPropertiesDefaults(
                        HystrixCommandProperties.Setter()
                                .withCircuitBreakerRequestVolumeThreshold(1)
                                .withCircuitBreakerSleepWindowInMilliseconds(30000)
                                .withCircuitBreakerErrorThresholdPercentage(1)
//                                .withCircuitBreakerForceOpen(true)
//                                .withCircuitBreakerForceClosed(true)
                                .withExecutionTimeoutEnabled(true)
                                .withExecutionTimeoutInMilliseconds(3000))
                .andThreadPoolPropertiesDefaults(
                        HystrixThreadPoolProperties.Setter()
                                .withCoreSize(10));
    }

    public LoginHystrixCommand() {
        super(getSetter());
    }

    @Override
    protected String run() throws Exception {
//        return ServiceMockUtil.mock();
        return ServiceMockUtil.mockSixtyFiveSecond();
    }

    @Override
    protected String getFallback() {
        return "hys failure";
    }

}

上面就模拟了一个登录的服务继承了HystrixCommand类。最好每一个方法都是一个Command,把业务封装在run中。

在构造函数中需要一个Setter来配置Hystrix,可以调整这些参数来改变Command的行为。

上面我们为了方便都是通过字面量的方式写在了程序之中。最常用的一些配置都包含在上面了,可以根据自己的理解,测试一下是否正确。

为了方便我们做一下简单的测试,这里我们来一个Controller类:

import cn.freemethod.hys.LoginHystrixCommand;
import cn.freemethod.service.ServiceMockUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HystrixController {

    @RequestMapping("/normal")
    @ResponseBody
    public String normal(){
//        return ServiceMockUtil.mock();
        return ServiceMockUtil.mockSixtyFiveSecond();
    }

    @RequestMapping("/hys")
    @ResponseBody
    public String hys(){
        LoginHystrixCommand command = new LoginHystrixCommand();
        return command.execute();
    }

    @RequestMapping("/gologin")
    public String goLogin(){
        return "dologin";
    }

}

其他配置文件稍后附录,这里先看使用ab简单的模拟测试一下:

一般接口测试

Hystrix接口测试

ab的参数-n表示请求的总数量,-c表示并发数量,所以上面模拟的是10000次请求,并发为200,我们可以从执行时间,平均请求执行时间,失败数量等来对比使用Hystrix和没有Hystrix的区别。

从上面我们可以看到使用Hystrix的失败的请求数很高,那是因为我们的熔断时间窗口设置的是30秒,整个10000请求执行的时间才16秒不到。

所以我们可以调整一下下面的三个参数:

HystrixCommandProperties.Setter()
                                .withCircuitBreakerRequestVolumeThreshold(10)
                                .withCircuitBreakerSleepWindowInMilliseconds(1000)
                                .withCircuitBreakerErrorThresholdPercentage(30)

上面的调整,表示并发数要达到10才有可能触发熔断,熔断时间1秒,然后重新接受部分流量开始统计,并且要错误率要达到30%之上才会触发熔断。

我们来看一下调整之后的测试结果:

Hystrix接口测试

其他配置文件

spring-application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

  <context:component-scan base-package="cn.freemethod">
    <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation" />
  </context:component-scan>

</beans>

dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc 
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:annotation-driven />
    <context:component-scan base-package="cn.freemethod.controller">
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation" />
  </context:component-scan>



  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="contentType" value="text/html; charset=utf-8"/>
    <property name="prefix" value="/WEB-INF/view/"/>
    <property name="suffix" value=".jsp" />
  </bean>

</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  
  <context-param>
    <param-name>webAppRootKey</param-name>
    <param-value>root</param-value>
  </context-param> 
  <!-- Sping配置文件 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring-application.xml</param-value>
  </context-param>

  <!--  Spring 容器启动监听器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

  <!-- 字符集 过滤器  -->
  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <!-- Spring view分发器 -->
  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>WEB-INF/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <!--<url-pattern>*.html</url-pattern>-->
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

其他jsp文件随便创建一个就可以了。

转载于:https://my.oschina.net/u/2474629/blog/1919954

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值