Hystrix實例與高併發測試

簡介

Hystrix配置中咱們簡單的瞭解了Hystrix經常使用的一些配置,這一篇咱們簡單的經過一些實例來加深對這些配置的理解。html

而且經過ab作一點簡單的併發測試,來看一下Hystrix對系統在流量比較高的時候的影響。java

模擬服務

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";
    }
}

先來一個模擬的服務的類,用來模擬服務的調用時間,經過隨機的方式讓休眠一些時間。web

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中。spring

在構造函數中須要一個Setter來配置Hystrix,能夠調整這些參數來改變Command的行爲。express

上面咱們爲了方便都是經過字面量的方式寫在了程序之中。最經常使用的一些配置都包含在上面了,能夠根據本身的理解,測試一下是否正確。spring-mvc

爲了方便咱們作一下簡單的測試,這裏咱們來一個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簡單的模擬測試一下:mvc

通常接口測試

Hystrix接口測試

ab的參數-n表示請求的總數量,-c表示併發數量,因此上面模擬的是10000次請求,併發爲200,咱們能夠從執行時間,平均請求執行時間,失敗數量等來對比使用Hystrix和沒有Hystrix的區別。app

從上面咱們能夠看到使用Hystrix的失敗的請求數很高,那是由於咱們的熔斷時間窗口設置的是30秒,整個10000請求執行的時間才16秒不到。dom

因此咱們能夠調整一下下面的三個參數:

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文件隨便建立一個就能夠了。

相關文章
相關標籤/搜索