1. 程式人生 > >關於springmvc的hello world的壓測報告

關於springmvc的hello world的壓測報告

  都說hello world 很簡單,應該能承受很大的請求壓力,那麼到底有多大?你知道嗎?如果知道,那咱們就不繼續了。如果不知道,我們來看一下!

1. 準備工作,快速建立一個基於springmvc的helloworld

1.1. 在pom.xml引入spring必須的包級日誌元件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation
="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.yougewe</groupId> <artifactId>mvn-local-test</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging
> <properties> <org.springframework.version>4.3.20.RELEASE</org.springframework.version> <freemarker.version>2.3.23</freemarker.version> <slf4j.version>1.7.12</slf4j.version> <mybatis.version>3.4.5</mybatis.version
> <aspectj.version>1.8.13</aspectj.version> </properties> <dependencies> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.44</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.8</version> </dependency> <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <!-- 不關注位置先 --> <!--<scope>test</scope>--> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client --> <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.1.1</version> </dependency> <!-- 配合slf4j使用 --> <!-- 日誌記錄 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> </dependencies> <build> <!--<finalName>sjd-yzbank-api</finalName>--> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.6</version> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.20.1</version> <configuration> <skipTests>false</skipTests> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-report-plugin</artifactId> <version>2.20.1</version> <!--<configuration> <includes> <include>**/*Test.java</include> </includes> </configuration>--> </plugin> <!-- clean外掛 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-clean-plugin</artifactId> </plugin> <!-- install外掛 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-install-plugin</artifactId> </plugin> <!-- deploy外掛 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> </plugin> <!-- dependency外掛 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> </plugin> <plugin> <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin --> <!-- 用於更好的編譯,如jdk版本太低等問題 --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>

 

1.2. 新增一個 web.xml, 只加一個dispatcherServlet 和一個字符集轉換過濾器

    <filter>
        <filter-name>SpringEncodingFilter</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>SpringEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- 防止Spring記憶體溢位監聽器 -->
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
    <!-- 如下 listener 會查詢 WEB-INF/applicationContext.xml 檔案 -->
    <!--<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>-->
    <!-- springMVC核心配置 -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!-- 攔截設定 -->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

 

1.3. 新增log4j.properties日誌配置檔案

log4j.rootLogger=DEBUG,console,im,logFile
log4j.additivity.org.apache=true
# 控制檯(console)
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d(%r) [%t] %-5p %l: %m %x %n
# 日誌檔案(logFile)
log4j.appender.logFile=org.apache.log4j.FileAppender
log4j.appender.logFile.Threshold=DEBUG
log4j.appender.logFile.ImmediateFlush=true
log4j.appender.logFile.Append=true
log4j.appender.logFile.File=D:/logs/log.log4j
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern=%d(%r) [%t] %-5p %l: %m %x %n
# 回滾檔案(rollingFile)
log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.Threshold=DEBUG
log4j.appender.rollingFile.ImmediateFlush=true
log4j.appender.rollingFile.Append=true
log4j.appender.rollingFile.File=D:/logs/log.log4j
log4j.appender.rollingFile.MaxFileSize=200KB
log4j.appender.rollingFile.MaxBackupIndex=50
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.ConversionPattern=%d(%r) [%t] %-5p %l: %m %x %n

 

1.4. 新增一個HelloController, 返回一個 字串

@RestController
@RequestMapping("/hello")
public class HelloController {

    @RequestMapping(value = "/world", method = {RequestMethod.GET, RequestMethod.POST}, produces = "application/json")
    @ResponseBody
    public Object world(@ModelAttribute UserInfo info) {
        return "hello world!";
    }
}

 

  好了,一切準備就緒!是時候讓我們來看一下它的能力如何了!

測試工具: jmeter + 臺式測試機一臺

前提1:
  機器配置: 4c8g 筆記本
  網絡卡: 高通 QCA9377, 共享頻寬: 100M, 網路測速: 下載:3.5MB/s 上傳:475KB/s
  web容器: tomcat7, 執行模式: apr(apache portable runtime)

壓測過程如下:

  併發100-5組連續請求, TPS: 146.2, error: 0, 平均響應時間: 0.381s, 最大響應時間: 2.44s

  server端cpu有一瞬間的飆高,記憶體幾乎無變化!

  下面,按照規律,翻倍併發,200-5組連續請求!看下資料!

  TPS增加了,為275;平均響應時間慢了點,0.429;沒有 error。

  再翻倍併發量:400-5組連續請求:

  TPS下降了,為208;平均響應時間翻番,1.1秒;不過幸好還是沒有error;

  再翻倍併發量:800-5組連續請求:

  TPS再次下降,為144;平均響應時間再翻番,3.6秒,這在生產環境已經不符合要求了!error仍為0;

   再翻倍: 1600-5組:

 

  注意,此時已經有error出現了,1.09%的錯誤率! TPS繼續下降: 93.4,平均響應時間繼續翻倍:8.9秒;

  綜上,springmvc的helloworld 能力差不多也就在1600了,因為已經有錯誤出現,在實際生產中已經完全不能接受了!

  不過,我還是想看一下server到底能承受多大壓力,也就是jvm完全宕機!

  壓到3000併發-5組:

  看起來還能響應,其實再server端,jvm已經掛掉了!所以結論是,tomcat7(apr模式)是扛不住3000併發的!

  降到2800,也依然jvm掛了!

   降到2600,jvm沒掛,但是錯誤量較多,由於錯誤導致併發只跑到12000就未能繼續進行了,資料不準:

   改了下失敗策略後,2600,還是掛了,重啟後可以扛住壓力!

  壓到4840個請求就掛了!

  2500併發,掛!

  2300併發,掛!

  2200併發,作業系統提示jre沒有響應,被迫關閉java程序!

  2000併發,掛!

  1900併發,扛住了!cpu在80左右跳動!記憶體不變!

  看來,1900還行,極限就2000吧!

 

  好了,tomcat7看來是沒轍了!

 

  換tomcat8 的 nio 看下效果!

前提2:

  tomcat8, nio 模式執行!

直接從2000併發開測!

併發2000-5組連續請求!

  server ok, 但是,仍然存在數錯誤,有幾個併發請求卡死! TPS: 62.9, 平均響應: 14.7s

 

  server ok, TPS: 77.2, error: 55%, 平均響應時間: 25s。只能說,服務端沒死,但是基本已經不怎麼可用了!

  到最後,我壓到 6000 的併發時,server 仍然沒有掛掉!

  所以,nio,是比較強悍的!