原生Servlet與Spring Controller效能比較
阿新 • • 發佈:2019-02-18
在實際專案工作,有同事提出,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檔案如下
在編寫Spring的配置檔案如下<!-- 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>
編寫一個簡單的Controller如下<?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>
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%"