整体机制:多个业务tomcat 多个图片tomcat 通过nginx 实现负载均衡,服务器部分缓存已经完成。现在需要实现客户端缓存。
1 设置nginx 缓存机制
请尊重知识,请尊重原创 更多资料参考请见 http://www.cezuwang.com/listFilm?page=1&areaId=906&filmTypeId=1
location ~ /photoserver/.*\.(gif|jpg|png|htm|jpeg|bmp|html|flv|ico|swf|doc)(.*) { #root nginx_cache/cache; if (!-f $request_filename) { proxy_pass http://img.dahongwa.com; #图片服务器 } proxy_cache_use_stale error timeout invalid_header http_500 http_502 http_503 http_504 http_404; proxy_cache_methods GET HEAD POST; proxy_cache_min_uses 1; expires max; access_log logs/img.dahongwa.com.log; }
2 配置图片tomcat过滤器
public class ResponseHeaderFilter implements Filter { /** The fc. */ FilterConfig fc; /* * (non-Javadoc) * * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, * javax.servlet.ServletResponse, javax.servlet.FilterChain) */ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; // set the provided HTTP response parameters for (Enumeration e = fc.getInitParameterNames(); e.hasMoreElements();) { String headerName = (String) e.nextElement(); response.setHeader(headerName, fc.getInitParameter(headerName)); } // pass the request/response on chain.doFilter(req, response); } /* * (non-Javadoc) * * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ public void init(FilterConfig filterConfig) { this.fc = filterConfig; } /* * (non-Javadoc) * * @see javax.servlet.Filter#destroy() */ public void destroy() { this.fc = null; }
配置图片tomcat web.xml文件
<filter> <filter-name>ResponseHeaderFilter</filter-name> <filter-class>com.legendshop.core.photo.ResponseHeaderFilter</filter-class> <init-param> <param-name>Cache-Control</param-name> <param-value>max-age=315360000</param-value> </init-param> <init-param> <param-name>Access-Control-Max-Age</param-name> <param-value>315360000</param-value> </init-param> <init-param> <param-name>Expires</param-name> <param-value>315360000</param-value> </init-param> </filter> <filter-mapping> <filter-name>ResponseHeaderFilter</filter-name> <url-pattern>/photoserver/photo/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>ResponseHeaderFilter</filter-name> <url-pattern>/photoserver/images/*</url-pattern> </filter-mapping>
3 在图片tmcat配置 过滤器 ETagContentFilter
<filter> <filter-name>ETagContentFilter</filter-name> <filter-class>com.legendshop.core.photo.ETagContentFilter</filter-class> <init-param> <param-name>Cache-Control</param-name> <param-value>max-age=315360000</param-value> </init-param> <init-param> <param-name>Access-Control-Max-Age</param-name> <param-value>315360000</param-value> </init-param> <init-param> <param-name>Expires</param-name> <param-value>315360000</param-value> </init-param> </filter> <filter-mapping> <filter-name>ETagContentFilter</filter-name> <url-pattern>/photoserver/photo/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>ETagContentFilter</filter-name> <url-pattern>/photoserver/images/*</url-pattern> </filter-mapping>
public class ETagContentFilter implements Filter { private static Logger logger = LoggerFactory.getLogger(ETagContentFilter.class); @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException { // TODO Auto-generated method stub HttpServletRequest servletRequest = (HttpServletRequest) req; HttpServletResponse servletResponse = (HttpServletResponse) res; ByteArrayOutputStream baos = new ByteArrayOutputStream(); ETagResponseWrapper wrappedResponse = new ETagResponseWrapper(servletResponse, baos); chain.doFilter(servletRequest, wrappedResponse); byte [] bytes = baos.toByteArray(); String token = '"' + ETagComputeUtils.getMd5Digest(bytes) + '"' ; servletResponse.setHeader( "ETag" , token); // always store the ETag in the header String previousToken = servletRequest.getHeader("If-None-Match"); if (previousToken != null && previousToken.equals(token)) { // compare previous token with current one logger.debug("ETag match: returning 304 Not Modified"); servletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED); // use the same date we sent when we created the ETag the first time through servletResponse.setHeader("Last-Modified",servletRequest.getHeader("If-Modified-Since")); // servletResponse.setHeader("Cache-Control",315360000); //Cache-Control: max-age=0 + Last-Modified(ETag) }else{ // first time through - set last modified time to now Calendar cal = Calendar.getInstance(); cal.set(Calendar.MILLISECOND, 0 ); Date lastModified = cal.getTime(); servletResponse.setDateHeader("Last-Modified", lastModified.getTime()); logger.debug( " Writing body content " ); servletResponse.setContentLength(bytes.length); ServletOutputStream sos = servletResponse.getOutputStream(); sos.write(bytes); sos.flush(); sos.close(); } } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub }
public class ETagResponseWrapper extends HttpServletResponseWrapper { private HttpServletResponse response = null; private ServletOutputStream stream = null; private PrintWriter writer = null; private OutputStream buffer = null; public ETagResponseWrapper( HttpServletResponse response, OutputStream buffer ) { super( response ); this.response = response; this.buffer = buffer; } public ServletOutputStream getOutputStream() throws IOException { if( stream == null ) stream = new ETagResponseStream( response, buffer ); return stream; } public PrintWriter getWriter() throws IOException { if( writer == null ) writer = new PrintWriter( new OutputStreamWriter( getOutputStream(), "UTF-8" ) ); return writer; } public void flushBuffer() throws IOException { stream.flush(); }
public class ETagResponseStream extends ServletOutputStream{ public ETagResponseStream(HttpServletResponse response,OutputStream outputstream)throws IOException { closed = false; stream = null; stream = outputstream; } public void close() throws IOException { if(!closed) { stream.close(); closed = true; } } public void flush() throws IOException { if(!closed) stream.flush(); } public void write(int i) throws IOException { if(!closed) stream.write((byte)i); } public void write(byte abyte0[], int i, int j) throws IOException { if(!closed) stream.write(abyte0, i, j); } public void write(byte abyte0[]) throws IOException { write(abyte0, 0, abyte0.length); } public boolean closed() { return closed; } public void reset() { } private boolean closed; private OutputStream stream; }
好了 下面你刷新就是一堆的304了,去玩吧。
相关推荐
最近学习Nginx+tomcat实现 负载均衡。 首先大家注意: 本文章中没有session共享,关于session共享我会在下一篇中讲解,先实现Nginx+tomcat负载均衡再实现session共享。 从网上查了好多资料,多走了很多弯路,现在把...
Nginx+Tomcat负载均衡&动静分离实战 从0开始构建Nginx WEB平台; 1)实战Tomcat WEB集群&代码发布; 2)Nginx负载均衡Tomcat集群&动静分离&Rewrite实战;
linux nginx+tomcat 负载均衡简单原理,其中以很简单明了的图片流程呈现nginx的负载均衡原理,当然其中也包含负载均衡的实例代码。供学者参考。
Nginx+Tomcat 搭建负载均衡三分钟搞定!!!!!!!!
Nginx+keepalived+tomcat实现性负载均衡
包含课件和源代码适合与开发人员和运维人员学习和深入理解
Nginx++Keepalived+Tomcat负载 均衡 &动 静 分 离。配置
Nginx+Tomcat+Redis实现负载均衡过程中session所需架包
nginx+tomcat实现负载均衡,共享session的两种方式: 1.使用Redis共享session 2.使用tomcat的组播功能。
nginx+tomcat7负载均衡+redis缓存session
nginx+tomcat负载均衡简单配置
Nginx+tomcat配置集群负载均衡实现动静分离实例
Nginx+tomcat负载均衡集群session复制 windos
小型网站上进行的nginx+tomcat负载均衡与动静分离
Nginx+tomcat 实现负载均衡session共享demo,和http://blog.csdn.net/u014513883/article/details/48550709 类似
nginx;tomcat;负载均衡实现参考文章
文档非常详细介绍了linux下nginx+tomcat负载均衡配置 包括nginx安装 nginx配置 tomcat配置 验证配置与测试负载均衡 nginx与tomcat动静态请求分离配置 nginx缓存配置。
nginx+redis负载均衡、session共享,基于redis+tomcat实现session同步的简单demo
keepalived+Nginx+Tomcat负载均衡配置文档,生产实施原文档,欢迎大家参考。
win7下nginx+tomcat负载均衡 第一次接触nginx自己花了半天时间研究的结果,和大家一同分享。