Shiroの複数回のアクセスを最適化する問題

32962 ワード

プロジェクトではredisを使用してshiroセッションの永続化とクラスタ共有を行うことができますが、実際のプロジェクトでは、ユーザーは次のようにログイン操作を行います.
2018-04-25 14:30:20.075 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroSessionDao -   session:b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.075 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.076 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroSessionDao -   session:b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.076 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.077 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.078 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroSessionDao -   session:b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.079 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.083 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.084 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.084 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.085 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.085 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.086 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroSessionDao -   session:b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.086 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.087 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.087 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.088 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroSessionDao -   session:b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.089 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.091 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3
2018-04-25 14:30:20.092 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :b0029f80-dbc5-40e6-8cbe-0dddaad69eb3

セッションはredisに永続化され、キャッシュサーバとしてredisを使用するため、shiroはリクエスト処理でセッションを使用する必要がある場合にredisからデータを取り出し、逆シーケンス化する.
このような簡単なアクセスでは、redisにアクセスする回数が多すぎて、DefaultSessionManagerのソースコードを表示します.
    //   session
    protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
        Serializable sessionId = getSessionId(sessionKey);
        if (sessionId == null) {
            log.debug("Unable to resolve session ID from SessionKey [{}].  Returning null to indicate a " +
                    "session could not be found.", sessionKey);
            return null;
        }

        //   session
        Session s = retrieveSessionFromDataSource(sessionId);
        if (s == null) {
            //session ID was provided, meaning one is expected to be found, but we couldn't find one:
            String msg = "Could not find session with ID [" + sessionId + "]";
            throw new UnknownSessionException(msg);
        }
        return s;
    }

    //   sessionDao,  session
    protected Session retrieveSessionFromDataSource(Serializable sessionId) throws UnknownSessionException {
        return sessionDAO.readSession(sessionId);
    }

基本手順:
  • sessionId
  • を取得
  • SessionDaoを呼び出すreadSession取得session
  • 分析:
  • ここでのSessionDaoは一般的にカスタマイズされており、redis永続化session
  • を使用しています.
  • 重要なのはretrieveSessionメソッドを見て、どのようにして1回のリクエスト内でretrieveSessionFromDataSourceを呼び出す回数を減らすことができます
  • 実行可能性メソッド:セッションを取得するときにセッションをキャッシュします.セッションキャッシュの役割ドメインとライフサイクル
  • に注意してください.
    ブレークポイント:
  • Web下でshiroを使用する場合、このセッションキーはWebSessionKeyタイプの
  • です.
  • WebSessionKeyこのクラスには、サーブレットRequest
  • という属性が含まれています.
    ソリューション:
  • 初めてセッションを取得した後、セッションオブジェクトをrequestに
  • 配置する
  • 単一リクエストサイクルでセッションを取得し、requestから
  • を直接取得する
  • リクエスト終了後requestは破棄された
  • SessionManagerをカスタマイズし、retrieveSessionメソッドを書き換え、sessionの取得方法を変更します.
    package com.ahut.shiro;
    
    import lombok.extern.slf4j.Slf4j;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.UnknownSessionException;
    import org.apache.shiro.session.mgt.SessionKey;
    import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
    import org.apache.shiro.web.session.mgt.WebSessionKey;
    
    import javax.servlet.ServletRequest;
    import java.io.Serializable;
    
    /**
     * @author cheng
     * @className: RedisShiroSessionManager
     * @description:    SessionManager
     * @dateTime 2018/4/25 14:41
     */
    @Slf4j
    public class RedisShiroSessionManager extends DefaultWebSessionManager {
    
        /**
         * @description:   session,             redis   
         * @author cheng
         * @dateTime 2018/4/25 14:43
         */
        @Override
        protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
            //   sessionId
            Serializable sessionId = getSessionId(sessionKey);
    
            ServletRequest request = null;
            //   Web     shiro     sessionKey   WebSessionKey    
            //    web   ,   request
            if (sessionKey instanceof WebSessionKey) {
                request = ((WebSessionKey) sessionKey).getServletRequest();
            }
    
            //    request   session
            if (request != null && sessionId != null) {
                Object sessionObj = request.getAttribute(sessionId.toString());
                if (sessionObj != null) {
                    log.info(" request   session:{}", sessionId);
                    return (Session) sessionObj;
                }
            }
    
            //   request   session  ,  redis   session,      session   request       
            Session session = super.retrieveSession(sessionKey);
            if (request != null && sessionId != null) {
                log.info("  session request :{}", sessionId);
                request.setAttribute(sessionId.toString(), session);
            }
    
            return session;
        }
    }

    ShiroConfig.JAvaでのカスタムSessionManagerの構成
        /**
         * @description:    sessionManager
         * @author cheng
         * @dateTime 2018/4/24 10:37
         */
        public SessionManager createMySessionManager() {
            RedisShiroSessionManager sessionManager = new RedisShiroSessionManager();
            //    sessionDao
            sessionManager.setSessionDAO(createRedisShiroSessionDao());
            // session     ,     
            sessionManager.setGlobalSessionTimeout(ShiroUtil.GLOBAL_SESSION_TIMEOUT);
            //      session
            sessionManager.setDeleteInvalidSessions(true);
            //    session    id   Cookie  ,     Cookie     
            sessionManager.setSessionIdCookie(createSessionIdCookie());
            //   sessionIdCookie           
            sessionManager.setSessionIdCookieEnabled(true);
            log.info("  sessionManager");
            return sessionManager;
        }
    
        /**
         * @description:        SecurityManager org.apache.shiro.mgt.SecurityManager,      
         * @author cheng
         * @dateTime 2018/4/18 15:48
         */
        public SecurityManager createSecurityManager() {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            //    realm
            securityManager.setRealm(createMyRealm());
            //    sessionManager
            securityManager.setSessionManager(createMySessionManager());
            //    rememberMeManager
            securityManager.setRememberMeManager(createRememberMeManager());
            //    cacheManager
            securityManager.setCacheManager(createCacheManager());
            log.info("  rsecurityManager");
            return securityManager;
        }

    最適化されたログ・アクセス・レコード
    2018-04-25 14:56:16.843 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroSessionDao -   session:8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.843 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.843 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroSessionDao -   session:8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.844 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.845 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.846 ahut [http-nio-8080-exec-1] INFO  c.a.shiro.RedisShiroSessionManager -   session request :8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.846 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroSessionDao -   session:8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.847 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.852 ahut [http-nio-8080-exec-1] INFO  c.a.shiro.RedisShiroSessionManager -  request   session:8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.852 ahut [http-nio-8080-exec-1] INFO  c.a.shiro.RedisShiroSessionManager -  request   session:8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.852 ahut [http-nio-8080-exec-1] INFO  c.a.shiro.RedisShiroSessionManager -  request   session:8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.852 ahut [http-nio-8080-exec-1] INFO  c.a.shiro.RedisShiroSessionManager -  request   session:8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.852 ahut [http-nio-8080-exec-1] INFO  c.a.shiro.RedisShiroSessionManager -  request   session:8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.853 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroSessionDao -   session:8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.853 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.854 ahut [http-nio-8080-exec-1] INFO  c.a.shiro.RedisShiroSessionManager -  request   session:8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.854 ahut [http-nio-8080-exec-1] INFO  c.a.shiro.RedisShiroSessionManager -  request   session:8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.854 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroSessionDao -   session:8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.855 ahut [http-nio-8080-exec-1] INFO  com.ahut.shiro.RedisShiroCache -         :8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.856 ahut [http-nio-8080-exec-1] INFO  c.a.shiro.RedisShiroSessionManager -  request   session:8475e279-8733-45d5-8fb7-08a371c4cd91
    2018-04-25 14:56:16.857 ahut [http-nio-8080-exec-1] INFO  c.a.shiro.RedisShiroSessionManager -  request   session:8475e279-8733-45d5-8fb7-08a371c4cd91