1. 程式人生 > >原生Servlet與Spring Controller效能比較

原生Servlet與Spring Controller效能比較

  在實際專案工作,有同事提出,Java原生的Servlet效能(響應速度與併發數)要比封裝過的Spring Controller高,基於這點,樓主用Apache的ab工具,對兩個簡單的應用做1000併發壓力測試,檢視兩者的響應速度與併發數、平均響應時間等引數。

原生Servlet應用描述:

  用簡單的方式,在eclipse中建立一個Dynamic Web project,然後建立一個Servlet,用註解的方式即可,這樣可以不用修改web.xml檔案,邏輯處理的模擬程式碼如下(執行緒休眠50ms,模擬實際的業務處理時間)  

/**
 * Servlet implementation class AbTestServlet
 */
@WebServlet("/AbTestServlet")
public class AbTestServlet extends HttpServlet {
<span style="white-space:pre">	</span>private static final long serialVersionUID = 1L;
       
    public AbTestServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
<span style="white-space:pre">	</span>System.out.println("Ab Test Servlet 響應 "+System.currentTimeMillis());
<span style="white-space:pre">	</span>try {
<span style="white-space:pre">		</span>Thread.sleep(50);
<span style="white-space:pre">	</span>    } catch (InterruptedException e) {
<span style="white-space:pre">		</span>e.printStackTrace();
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>response.getWriter().append("Served at: ").append(request.getContextPath());
<span style="white-space:pre">	</span>}

      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
<span style="white-space:pre">	</span>// TODO Auto-generated method stub
<span style="white-space:pre">	</span>doGet(request, response);
     }
}

Spring Controller應用描述:

  建立一個簡單的maven專案,只匯入spring-webmvc與spring-context即可(版本4.2.5),編寫專案的web.xml檔案如下

	<!-- 4:加入Spring Context 配置檔案 與 Listener -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:/config/application-context.xml</param-value>
	</context-param>
	
	<!-- 4:加入Spring Context 配置檔案 與 Listener -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- 1:啟動Spring的MVC  DispatcherServlet -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value></param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
		<async-supported>true</async-supported>
	</servlet>
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
  在編寫Spring的配置檔案如下
<?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:aop="http://www.springframework.org/schema/aop"    
    xmlns:tx="http://www.springframework.org/schema/tx"    
    xmlns:context="http://www.springframework.org/schema/context"    
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    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" >  
	
    <!-- 完成請求和註解POJO的對映(啟用@Controller模式  ),它會自動註冊DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter兩個bean, 這兩個bean是spring MVC為@Controllers分發請求所必須的  -->
    <mvc:annotation-driven/> 
	<!-- 自動掃描元件Service -->  
	<context:component-scan base-package="com.cloud.abtest"/>
</beans>
  編寫一個簡單的Controller如下
package com.cloud.abtest.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;


@Controller
public class AbTestController {
	
	@RequestMapping("/AbTestController")
	@ResponseBody
	public String login(HttpServletRequest request, HttpServletResponse response) throws Exception{
		
		System.out.println("Ab Test Controller 響應 "+System.currentTimeMillis());
		try {
			Thread.sleep(50);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return "Served at: "+request.getContextPath();
	}

}
controller專案原始碼下載地址

對原生Servlet專案進行併發壓力測試命令和結果如下:
<span style="white-space:pre">	</span>命令為: ab -n 1000 -c 1000 http://localhost:8080/AbtestServlet/AbTestServlet
	Apache24\bin>ab -n 1000 -c 1000 http://localhost:8080/AbtestServlet/AbTestServlet
	This is ApacheBench, Version 2.3 <$Revision: 1748469 $>
	Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
	Licensed to The Apache Software Foundation, http://www.apache.org/
	
	Benchmarking localhost (be patient)
	Completed 100 requests
	Completed 200 requests
	Completed 300 requests
	Completed 400 requests
	Completed 500 requests
	Completed 600 requests
	Completed 700 requests
	Completed 800 requests
	Completed 900 requests
	Completed 1000 requests
	Finished 1000 requests
	
	
	Server Software:        Apache-Coyote/1.1
	Server Hostname:        localhost
	Server Port:            8080
	
	Document Path:          /AbtestServlet/AbTestServlet
	Document Length:        25 bytes
	
	Concurrency Level:      1000
		<span style="background-color: rgb(51, 204, 0);">(併發執行緒數)</span>
	Time taken for tests:   0.850 seconds
		<span style="background-color: rgb(51, 204, 0);">(使用時間)</span>
	Complete requests:      1000
		<span style="background-color: rgb(51, 255, 51);">(成功的請求數量)</span>
	Failed requests:        0
		<span style="background-color: rgb(51, 255, 51);">(失敗的請求數量)</span>
	Total transferred:      147000 bytes
		<span style="background-color: rgb(51, 255, 51);">(全部使用的流量)</span>
	HTML transferred:       25000 bytes
		<span style="background-color: rgb(51, 255, 51);">(Html檔案使用的流量)</span>
	Requests per second:    1176.40 [#/sec] (mean)
		<span style="background-color: rgb(51, 255, 51);">(指標一 平均每秒請求數)</span>
	Time per request:       850.049 [ms] (mean)(測了好幾次,500,800,1200都有,平均1000左右)
		<span style="background-color: rgb(51, 255, 51);">(指標二 平均事務響應時間)</span>
	Time per request:       0.850 [ms] (mean, across all concurrent requests)
		<span style="background-color: rgb(51, 255, 51);">(平均請求時間)</span>
	Transfer rate:          168.88 [Kbytes/sec] received
		<span style="background-color: rgb(51, 255, 51);">(傳輸速率)</span>
	
	Connection Times (ms)
	              min  mean[+/-sd] median   max
	Connect:        0    0   1.0      0      18
	Processing:   302  486  81.3    504     600
	Waiting:       93  392  91.2    394     546
	Total:        303  486  81.3    504     601
		<span style="background-color: rgb(51, 255, 51);">(所有請求的響應情況)</span>
	
	Percentage of the requests served within a certain time (ms)
	  50%    504
	  66%    545
	  75%    556
	  80%    562
	  90%    576
	  95%    585
	  98%    596
	  99%    599
	 100%    601 (longest request)
		<span style="background-color: rgb(51, 255, 51);">每個請求都有一個響應時間 。。 
		比如 其中 50% 的使用者響應時間小於 504 毫秒 。。 
		最大的響應時間小於 601 毫秒 (100% 處) 。。 </span>

對Controller專案進行併發壓力測試命令和結果如下:
<span style="white-space:pre">	</span>命令為: ab -n 1000 -c 1000 http://localhost:8080/abTestController/AbTestController
	Apache24\bin>ab -n 1000 -c 1000 http://localhost:8080/abTestController/AbTestControll
	This is ApacheBench, Version 2.3 <$Revision: 1748469 $>
	Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
	Licensed to The Apache Software Foundation, http://www.apache.org/
	
	Benchmarking localhost (be patient)
	Completed 100 requests
	Completed 200 requests
	Completed 300 requests
	Completed 400 requests
	Completed 500 requests
	Completed 600 requests
	Completed 700 requests
	Completed 800 requests
	Completed 900 requests
	Completed 1000 requests
	Finished 1000 requests
	
	
	Server Software:        Apache-Coyote/1.1
	Server Hostname:        localhost
	Server Port:            8080
	
	Document Path:          /abTestController/AbTestController
	Document Length:        28 bytes
	
	Concurrency Level:      1000
	Time taken for tests:   0.676 seconds
	Complete requests:      1000
	Failed requests:        0
	Total transferred:      195000 bytes
	HTML transferred:       28000 bytes
	<span style="background-color: rgb(51, 255, 51);">Requests per second:    1479.20 [#/sec] (mean)</span>
	Time per request:       676.039 [ms] (mean)
	Time per request:       0.676 [ms] (mean, across all concurrent requests)</span>
	Transfer rate:          281.68 [Kbytes/sec] received
	
	Connection Times (ms)
	              min  mean[+/-sd] median   max
	Connect:        0    0   0.5      0       4
	Processing:    96  325 107.4    358     475
	Waiting:       79  300 108.5    325     475
	Total:         96  325 107.4    358     476

結論:

  總體而言Servlet的併發與響應時間比Controller稍微好一些(同一個tomcat),但是幾乎體現不出來,樓主貼的結果中Controller結果要好於Servlet的原因是剛好貼了個Controller效果好的,實際測試中每一個專案樓主都用1000的併發量測試好幾十次,效果都差不多。

  PS:如果需要測試的URL是帶引數的,需要用""號將URL包裹在裡面,如下所示:

ab -n 1000 -c 1000 "http://localhost:8080/AbtestServlet/AbTestServlet?sId=1476067342641247&sourceId=0&test=10%KDO%"