如何实现基于filter的html静态化

AB测试数据,显示处理速度接近提升20倍([color=red]红色文字[/color]),[color=red]并且在未开启时出现了大量的失败[/color]。

[quote]

[b]mysql连接为默认设置[/b]

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

[/quote]


[quote]

[b]启用缓存时测试数据,红字部分[/b]

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
[color=red]Complete requests: 1000
Failed requests: 0[/color]
Write errors: 0
Non-2xx responses: 1000
Total transferred: 109000 bytes
HTML transferred: 0 bytes
[color=red]Requests per second: 98.31 [#/sec] (mean)
Time per request: 101.719 [ms] (mean)[/color]
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)

---------------------------------------------------------------------------------------------------

[b]关闭缓存时测试数据,红字部分[/b]

C:\Documents and Settings\Administrator>ab -n 1000 -c 10 http://www.abc.com/[color=red]?refresh=true[/color]
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
[color=red]Complete requests: 1000[/color]
[size=large][color=red]Failed requests: 503
(Connect: 0, Receive: 0, Length: 503, Exceptions: 0)[/color][/size]
Write errors: 0
Non-2xx responses: 503
Total transferred: 10479297 bytes
HTML transferred: 10131345 bytes
[color=red]Requests per second: 5.17 [#/sec] (mean)
Time per request: 1934.063 [ms] (mean)[/color]
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)

[/quote]

-------------------------
[b]实现思路[/b]

[quote]以URL为key,ehcache为容器,如果容器中存在html结果,直接返回,如果没有,继续生成,返回后的结果放入容器,同时将结果返回给客户端,结束流程。[/quote]

组成构建:

1.[b]HtmlStaticFilter [/b]



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:[b]ResponseWrapper[/b]





/**
* 自定义一个响应结果包装器,将在这里提供一个基于内存的输出器来存储所有 返回给客户端的原始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.[b]Xcache实现类EhcacheXcache[/b]



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.[b]基于spring管理的filter[/b]
[quote]

[b]web.xml[/b]

<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>


[b]spring配置文件[/b]

<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>

[/quote]


[b]完。[/b]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值