AB测试数据,显示处理速度接近提升20倍(红色文字),并且在未开启时出现了大量的失败。
引用
mysql连接为默认设置
ERROR [http-80-5] JDBCExceptionReporter.logExceptions(78) | Unable to connect to any hosts due to exception: java.net.SocketException: java.net.ConnectException: Connection refused: connect
** BEGIN NESTED EXCEPTION **
java.net.SocketException
MESSAGE: java.net.ConnectException: Connection refused: connect
STACKTRACE:
java.net.SocketException: java.net.ConnectException: Connection refused: connect
引用
启用缓存时测试数据,红字部分
C:\Documents and Settings\Administrator>ab -n 1000 -c 10 http://www.abc.com/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking www.abc.com (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: www.abc.com
Server Port: 80
Document Path: /
Document Length: 0 bytes
Concurrency Level: 10
Time taken for tests: 10.172 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Non-2xx responses: 1000
Total transferred: 109000 bytes
HTML transferred: 0 bytes
Requests per second: 98.31 [#/sec] (mean)
Time per request: 101.719 [ms] (mean)
Time per request: 10.172 [ms] (mean, across all concurrent requests)
Transfer rate: 10.46 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.9 0 16
Processing: 16 101 11.4 109 125
Waiting: 0 51 27.7 47 109
Total: 16 101 11.4 109 125
Percentage of the requests served within a certain time (ms)
50% 109
66% 109
75% 109
80% 109
90% 109
95% 109
98% 109
99% 109
100% 125 (longest request)
---------------------------------------------------------------
关闭缓存时测试数据,红字部分
C:\Documents and Settings\Administrator>ab -n 1000 -c 10 http://www.abc.com/?refresh=true
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking www.abc.com (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: www.abc.com
Server Port: 80
Document Path: /?refresh=true
Document Length: 20385 bytes
Concurrency Level: 10
Time taken for tests: 193.406 seconds
Complete requests: 1000
Failed requests: 503
(Connect: 0, Receive: 0, Length: 503, Exceptions: 0)
Write errors: 0
Non-2xx responses: 503
Total transferred: 10479297 bytes
HTML transferred: 10131345 bytes
Requests per second: 5.17 [#/sec] (mean)
Time per request: 1934.063 [ms] (mean)
Time per request: 193.406 [ms] (mean, across all concurrent requests)
Transfer rate: 52.91 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 4.3 0 31
Processing: 94 1906 1426.7 2000 8234
Waiting: 94 1893 1428.6 1984 8234
Total: 94 1907 1426.2 2000 8234
Percentage of the requests served within a certain time (ms)
50% 2000
66% 2031
75% 3000
80% 3016
90% 4016
95% 5016
98% 6031
99% 6063
100% 8234 (longest request)
-------------------------
实现思路
引用
以URL为key,ehcache为容器,如果容器中存在html结果,直接返回,如果没有,继续生成,返回后的结果放入容器,同时将结果返回给客户端,结束流程。
组成构建:
1.HtmlStaticFilter
public class HtmlStaticFilter implements Filter { private static final Log log = LogFactory.getLog(HtmlStaticFilter.class); private Xcache xcache; public Xcache getXcache() { return xcache; } public void setXcache(Xcache xcache) { this.xcache = xcache; } private static int counter = 0; public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { String refresh = request.getParameter("refresh"); if (StringUtils.isNotBlank(refresh) &&refresh.equals("true")) { filterChain.doFilter(request, response); return; } /** * 获取请求url作为缓存的KEY */ String urlKey = request.getServerName() + ((HttpServletRequest) request).getRequestURI(); // 不缓存非html请求. js css img 跳过 if (!urlKey.endsWith(".html") && !urlKey.endsWith("/")) { filterChain.doFilter(request, response); return; } log.error(++counter + ":url=====>" + urlKey); /** * 查看缓存中是否有此文件,如果有,返回文件 */ String content = (String) xcache.get(urlKey); if (content == null) { log.error("content=====>" + content);// 应该只出现一次 // 使用我们自定义的响应包装器来包装原始的ServletResponse ResponseWrapper wrapper = new ResponseWrapper( (HttpServletResponse) response); /** * 如果没有,继续请求,获取请求后返回的结果,放入缓存中。 */ // 这句话非常重要,注意看到第二个参数是我们的包装器而不是response filterChain.doFilter(request, wrapper); // 处理截获的结果并进行处理,比如替换所有的“名称”为“铁木箱子” content = wrapper.getResult(); xcache.set(urlKey, content); } /** * 返回请求结果给客户端 */ response.setCharacterEncoding("UTF-8"); // 重置响应输出的内容长度 response.setContentLength(-1); // 输出最终的结果 PrintWriter out = response.getWriter(); out.write(content); out.flush(); out.close(); } @Override public void destroy() { } @Override public void init(FilterConfig arg0) throws ServletException { } }
构件2:ResponseWrapper
/** * 自定义一个响应结果包装器,将在这里提供一个基于内存的输出器来存储所有 返回给客户端的原始HTML代码。 * * @author 铁木箱子 * */ public class ResponseWrapper extends HttpServletResponseWrapper { private PrintWriter cachedWriter; private CharArrayWriter bufferedWriter; public ResponseWrapper(HttpServletResponse response) { super(response); // 这个是我们保存返回结果的地方 bufferedWriter = new CharArrayWriter(); // 这个是包装PrintWriter的,让所有结果通过这个PrintWriter写入到bufferedWriter中 cachedWriter = new PrintWriter(bufferedWriter); } @Override public PrintWriter getWriter() { return cachedWriter; } /** * 获取原始的HTML页面内容。 * * @return */ public String getResult() { return bufferedWriter.toString(); } }
3.Xcache实现类EhcacheXcache
public class EhcacheXcache implements Xcache { private Cache cache; public Cache getCache() { return cache; } public void setCache(Cache cache) { this.cache = cache; } public Object get(Object key) { Element e = (Element) cache.get(key); if (e != null) { return e.getValue(); } return null; } public void set(String key, Object value) { Element e = new Element(key, value); cache.put(e); } @Override public String getName() { return cache.getName(); } }
4.基于spring管理的filter
引用
web.xml
<filter>
<filter-name>htmlStaticFilter</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>htmlStaticFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
spring配置文件
<bean id="htmlStaticFilter" class="com.webapp.filter.HtmlStaticFilter">
<property name="xcache">
<ref bean="xcache" />
</property>
</bean>
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
</bean>
<bean id="htmlCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager"></property>
<property name="cacheName" value="htmlCache"></property>
</bean>
<bean id="xcache" class="com.cache.EhcacheXcache">
<property name="cache" ref="htmlCache"></property>
</bean>
完。