redisはサーバ間セッション共有を実現


一般的に、サーバクラスタを作成するときにnginx逆プロキシサーバを構成します.しかし、問題が発生しました.複数のサーバ間のセッションはどのように共有されていますか?
私がここで使っているのはredisで、構想を実現しています.
1.sessionId生成ポリシーを自分で定義し、session.setAttribute操作の際、CSESSIONIDを生成してサーバーに書き込みます.
2.filterブロッキング要求、拡張HttpServertRequest、エージェントsession実装クラス、拡張setAttributeメソッド、getAttributeメソッドを定義します.
3.クッキーのライフサイクルとredisのキーのライフサイクルの更新を要求するたびに、私がここで設定したのは30分です.
私のコードは優雅ではなく、拡張も行われていません.以下に私の実装を貼ります.
1.簡単なredis実現:
実際の開発ではspringとプールを統合して構成してください
import redis.clients.jedis.Jedis;

public class JedisProvider {

	 private static Jedis jedis;
	 
	 public static Jedis getJedis() {
		 jedis = new Jedis("127.0.0.1", 6379);
 
		 return jedis;
	 }
	 
//	 public static void main(String[] args) {
//		Jedis jedis = getJedis();
//		jedis.set("name", "tanlei");
//	}
}

2.CookieUtil
</pre><p><pre name="code" class="java">import java.util.UUID;

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

public class CookieUtil {
	
	 public static String cacheCSessionId = null;
	 public static Integer KEY_EXPIRE_TIME = 30 * 60;
	
	/**
	 *   JessionId
	 * 
	 * @param request
	 * @return
	 */
	public static String getJsessionId(HttpServletRequest request) {
		Cookie[] cookies = request.getCookies();
		// 2: Cookie          CSESSIONID
		if (null != cookies && cookies.length > 0) {
			for (Cookie cookie : cookies) {
				if ("CSESSIONID".equals(cookie.getName())) {
					//       
					return cookie.getValue();
				} 
			}
		}
		return null;
	}

<pre name="code" class="java">public static String addCookie(HttpServletRequest request, HttpServletResponse response, Integer KEY_EXPIRE_TIME) {
		String csessionId = getJsessionId(request);
		if(csessionId == null || "".equals(csessionId)) {
			csessionId = UUID.randomUUID().toString().replaceAll("-", "");
		}
		Cookie cookie = new Cookie("CSESSIONID", csessionId);
		cookie.setPath("/");
		cookie.setMaxAge(KEY_EXPIRE_TIME);
		response.addCookie(cookie);
		return csessionId;
	}
}
 
 
 
 

3.sessionfilter

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.tanlei.bean.User;
import com.tanlei.jedis.provider.CookieUtil;
import com.tanlei.jedis.provider.JedisProvider;

import redis.clients.jedis.Jedis;

public class SessionFilter implements Filter{
	 private Jedis jedis = JedisProvider.getJedis();
	
	@Override
	public void destroy() {
		
	}
@Override
	public void doFilter(ServletRequest req, ServletResponse rep, FilterChain chain)
			throws IOException, ServletException {
		// session      ,   cookie     redis       
		String csessionId = CookieUtil.getJsessionId((HttpServletRequest) req);
		if(csessionId != null && !"".equals(csessionId)) {
			jedis.expire(csessionId, CookieUtil.KEY_EXPIRE_TIME);
			CookieUtil.addCookie((HttpServletRequest) req, (HttpServletResponse)rep, CookieUtil.KEY_EXPIRE_TIME);
		}
		
//		HttpSession session = ((HttpServletRequest)req).getSession();
//		if(session != null) {
//			String jSessionId = CookieUtil.getJessionId((HttpServletRequest)req); // cookie   ,    cookie      30  
//			jedis.expire(jSessionId, 60 * 30);
//		}
		chain.doFilter(new RemoteSessionRequest((HttpServletRequest) req, (HttpServletResponse)rep), rep);
		CookieUtil.cacheCSessionId= null;
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		
	}

}

4.RemoteSessionRequest
class RemoteSessionRequest extends HttpServletRequestWrapper {
	 private HttpServletRequest request;
	 private HttpServletResponse response;
	
	public RemoteSessionRequest(HttpServletRequest request, HttpServletResponse response) {
		super(request);
		this.request = request;
		this.response = response;
	}

	@Override
	public HttpSession getSession() {
		 return RemoteSessionHandler.getInstance(super.getSession(),request, response);
	}
	
	
}

5.RemoteSessionHandler
class RemoteSessionHandler implements InvocationHandler {
   private Jedis jedis = JedisProvider.getJedis();

    private HttpSession session = null;
    private HttpServletRequest request = null;
    private HttpServletResponse response = null;

    private RemoteSessionHandler(HttpSession httpSession, HttpServletRequest request, HttpServletResponse response) {
        this.session = httpSession;
        this.request = request;
        this.response = response;
    };

    public static HttpSession getInstance(HttpSession httpSession, HttpServletRequest request,HttpServletResponse response) {
        InvocationHandler handler = new RemoteSessionHandler(httpSession, request, response);
        return (HttpSession) Proxy.newProxyInstance(httpSession.getClass().getClassLoader(), httpSession.getClass().getInterfaces(), handler);
    }
 @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if ("setAttribute".equals(method.getName())) {
        	String csessionId = CookieUtil.getJsessionId(request); //  cookie,csessionId
        	if(csessionId == null || "".equals(csessionId)) {
        		csessionId = CookieUtil.addCookie(request, response, CookieUtil.KEY_EXPIRE_TIME);
        		CookieUtil.cacheCSessionId = csessionId;
        	}
        	<pre name="code" class="java">         } else if ("getAttribute".equals(method.getName())) {
        	String csessionId = CookieUtil.getJsessionId(request); // cookie   
        	if(csessionId == null || "".equals(csessionId)) {
        		// cacheCSessionId   ,   
        		if(CookieUtil.cacheCSessionId == null || "".equals(CookieUtil.cacheCSessionId)) {
        			return null;
        		} else {
        			csessionId = CookieUtil.cacheCSessionId;
        		}
        	}
            //  csessionid redis    
        	Set<String> userIds = jedis.hkeys(csessionId);
        	String userId = null;
        	for(String id : userIds) {
        		userId = id;
        	}
        	User user = null;
        	if(userIds.size() > 0) {
        		String userName = jedis.hget(csessionId, userId);
        		 user = new User(Integer.parseInt(userId), userName);
        	}
        	//       ,    
        	CookieUtil.cacheCSessionId = null;
            return user;
        }

//キーがある場合は、設定する必要はなく、requestのブロッキングでセッションの有効期限if(jedis.exists(csessionId)){return null;を設定します.String userName = ((User)args[1]).getUserName();//csessionidをkeyとし、ユーザー名はfield、ユーザーidはvalueである.String userId = ((User)args[1]).getId().toString(); jedis.hset(csessionId, userId, userName); jedis.expire(csessionId, CookieUtil.KEY_EXPIRE_TIME); return null;
 
 
         }
        return method.invoke(session, args);
    }

}

6.web.xml
<filter>
    <filter-name>SessionFilter</filter-name>
    <filter-class>
            com.tanlei.filter.SessionFilter
        </filter-class>
  </filter>
  <filter-mapping>
    <filter-name>SessionFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <servlet>
      <servlet-name>sessionSetServlet</servlet-name>
      <servlet-class>com.tanlei.controller.SessionSetServlet</servlet-class>
  </servlet>

  <servlet-mapping>  
      <servlet-name>sessionSetServlet</servlet-name>
      <url-pattern>/sessionSetServlet</url-pattern>
  </servlet-mapping>
  
<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

7.controller(servlet)
public class SessionSetServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("1111");
		HttpSession session= request.getSession();
		session.setAttribute("user", new User(2, "ergou"));
		System.out.println(request.getContextPath());
		//response.sendRedirect(request.getContextPath() + "/index.jsp");
		request.getRequestDispatcher("index.jsp").forward(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

8.jarパッケージに依存する:
commons-logging-1.1.3.jar
jedis-2.7.2.jar
redisをテストするには、次のようにします.
redis 64-3.0.501(windowsベース)
9.Userエンティティ:
public class User {

	private Integer id;
	private String userName;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getUserName() {
		return userName;
	}
	
	

	public User(Integer id, String userName) {
		super();
		this.id = id;
		this.userName = userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

}