分散ロック獲得トークン

パッケージcom.sankuai.qcs.regulation.nanjing.util。

輸入com.dianping.squirrel.client.StoreKey。
輸入com.dianping.squirrel.client.impl.redis.RedisStoreClient。
輸入com.dianping.zebra.util.StringUtils。
輸入com.google.common.collect.Maps。
輸入com.sankuai.meituan.config.MtConfigClient。
輸入com.sankuai.qcs.regulation.nanjing.Conf。
輸入org.apache.http.HttpException。
輸入org.slf4j.Logger。
輸入org.slf4j.LoggerFactory; 
輸入org.springframework.stereotype.Component。

輸入javax.annotation.Resource。
輸入java.util.Map; 

/ * * 
 *説明:
 * tanxiaoleiのによって作成
 *発売日:2018年4月20日午前11時50分
 * /
@Component 
パブリック クラスTokenUtils { 

    プライベート 静的最終ロガーロガー= LoggerFactory.getLogger(TokenUtils。クラス)。

    @Resource 
    プライベートRedisStoreClient redisStoreClientを。
    @Resource 
    プライベートMtConfigClient mtConfigClientを。

    プライベート 静的な最終文字列KEY_CATEGORY = regulation_traffic プライベート 静的 =最終文字列TOKEN_KEY_PARAMS nanjing_token_key // 缓存失效时间11个小时
    プライベート 静的最終int型TOKEN_EXPIRE_SECONDS = 39600 ; 

    プライベート 静的 =最終文字列LOCK_KEY_PARAMS nanjing_lock_key // 分布式锁失效时间2秒
    プライベート 静的最終int型 LOCK_EXPIRE_SECONDS = 2 ; 

    プライベート 静的な最終文字列NJ_TOKEN_USERID = NJ_TOKEN_USERID 

    プライベート 静的最終地図<文字列、文字列>ヘッダ= Maps.newHashMap(); 

    静的{ 
        headers.put(接続キープアライブ" ); 
        headers.put(" -文字セット受け入れ"Conf.DEFAULT_CHARSET); 
        headers.put(" コンテンツタイプ、Conf.ContentType.JSON.getMimeTypeを()); 
    } / * * 
     *判断トークン是否在Redisの存在
     * 
     * @return * / パブリックブールtokenExists(){ 
        StoreKeyキー = 新しいStoreKey(KEY_CATEGORY、TOKEN_KEY_PARAMS);
         返す(キー)redisStoreClient.exists; 
    } / * * 
     *删除指定トークン
     * 
     * @return * / 公共

    
     
    

    
     
     ボイドdelToken(){ 
        StoreKeyキー = 新しいStoreKey(KEY_CATEGORY、TOKEN_KEY_PARAMS)。
        LOGGER.infoは(" キー:{}} {削除" 、キー、redisStoreClient.delete(キー))。
    } 

    / * * 
     *获取トークン
     * 
     * @return 
     * / 
    パブリック文字列入手トークン(){ 
        StoreKeyキー = 新しいStoreKey(KEY_CATEGORY、TOKEN_KEY_PARAMS)。
        トークン文字列 = redisStoreClient。取得(キー); 
        LOGGER.info(" トークン得る:{}のRedisから" 、トークン)。
        IF(トークン== nullの){ 
            storekeyのロック = 新しい新storekey(KEY_CATEGORY、LOCK_KEY_PARAMS);
             // 分散ロックあなたがロックを取得しない場合は、直接それによって消費MQ影響し、サービスの問題南京側を防ぐために、放棄する
            IF(redisStoreClient.setnxを(ロック" ロック" 、LOCK_EXPIRE_SECONDS)){
                 // 重複を防ぐために、ダブルチェック、トークンを取得 
                トークン= redisStoreClientを。GET )(キー;
                 IF(トークン== nullの){
                     試み{ 
                        文字列のuserId =mtConfigClient.getValue(NJ_TOKEN_USERID)。
                        LOGGER.info(" mtConfigClientはUSERIDは得る:{} " 、USERID)。
                        トークン = HttpClientUtils.post(" のhttp:// " + Conf.GET_TOKEN_URL +はuserId、" 320100 " 、ヘッダ); 
                        LOGGER.info(" トークン得る:{} HTTPから" 、トークン)。
                        もし(StringUtils.isNotBlank(トークン)){ 
                            redisStoreClient。セット(キー、トークン、TOKEN_EXPIRE_SECONDS)。
                        }
                    } キャッチ(HttpException E){ 
                        LOGGER.error(" errerトークンGET " 、E); 
                    } 
                } 
                // 分散を直接ロックして期限切れに 
                redisStoreClient.expire(ロック0 ); 
            } 
        } 
        戻りトークンを、
    } 
}
パッケージcom.sankuai.qcs.regulation.nanjing.util。

輸入com.sankuai.qcs.regulation.nanjing.Conf。
輸入org.slf4j.Logger。
輸入org.slf4j.LoggerFactory; 
輸入org.springframework.context.ApplicationContext; 
輸入org.springframework.stereotype.Component。

輸入javax.websocket.ClientEndpoint。
輸入javax.websocket.CloseReason。
輸入javax.websocket.OnClose。
輸入javax.websocket.OnError。
輸入javax.websocket.OnMessage。
輸入javax.websocket.OnOpen。
輸入javax.websocket.Session。

/ * * 
 *説明:
 * tanxiaoleiのによって作成
 *発売日:2018年4月18日14時26分
 * / 
@ClientEndpoint
@Component 
パブリック クラスWebSocketClientUtils { 


//     @Autowired
 //     プライベートTokenUtilsのtokenUtils。

    プライベート 静的最終ロガーLOGGER = LoggerFactory.getLogger(WebSocketClientUtils。クラス); 

    プライベート 静的のApplicationContextのApplicationContext。

    パブリック 静的ApplicationContextのgetApplicationContext(){
         戻りのApplicationContextと、
    } 

    パブリック 静的 ボイドsetApplicationContext(ApplicationContextのApplicationContextの){ 
        WebSocketClientUtils.applicationContext =ApplicationContextの; 
    }

    @OnOpen 
    公共 ボイド開く時(セッションsession){
         // 经过试验、客户端设置バッファサイズ时并不生效
        session.setMaxBinaryMessageBufferSize(Conf.BINARY_MESSAGE_BUFFER_SIZE)。
        session.setMaxTextMessageBufferSize(Conf.BINARY_MESSAGE_BUFFER_SIZE)。
        LOGGER.info(" セッション{}、{}接続" 、session.getId()、session.getRequestParameterMap())。
    } 

    @OnMessage 
    公共 ボイドのonMessage(文字列メッセージ、セッションsession){ 
        LOGGER.info(" セッションメッセージを受け取る:{} " 、メッセージ)。
        //失效如果是403、表示トークン
        であれば" 403 " .equals(メッセージ)){ 
            delAndGetNewToken()。
        } 
    } 

    @OnClose 
    公共 ボイド{(セッションセッション、CloseReason closeReason)OnCloseの
        (LOGGER.info " なぜなら} {セッションの最大バッファサイズ{} {}近い" session.getMaxBinaryMessageBufferSize()、session.getRequestParameterMap()、closeReason)。
    } 

    @OnError 
    公共 のボイドのonError(セッションsession、Throwableをスロー可能){
         場合(セッション!= nullの){ 
            LOGGER.error(" セッション{}エラー"、スロー可能session.getRequestParameterMap())。
        } { 
            LOGGER.error(" エラー" 、スロー可能)。
        } 
    } 

    プライベート ボイドdelAndGetNewToken(){ 
        TokenUtils tokenUtils =(TokenUtils)applicationContext.getBean(TokenUtils。クラス)。
        LOGGER.info(" toeknUtils:{} " 、tokenUtils)。
        tokenUtils.delToken(); 
        LOGGER.info(" 再びトークンを取得:{} " 、tokenUtils.getToken())。
    } 

}

 

    / * * 
     キーが既に既存の値を変更することなく、存在する場合、キーが存在しない場合にのみ追加した場合*キー、値の加算値に対応
     *#{@link RedisStoreClient追加(Storekey、オブジェクト、INT)} 
     * @paramキーを追加するには、キー
     値を追加する* @param値を
     * @paramのexpireInSecondsの有効期限の
     キーが存在し、正常trueに<BR>リターンを追加していない場合は*の@returnの
     キーがすでに存在する場合*は、falseを返します
     * @throws StoreException例外はあります必要に応じてStoreExceptionサブクラスとのRuntimeExceptionでは、対応する例外をキャプチャすることができます。
     *として:あなたはタイムアウト例外をキャプチャする必要がある場合は、StoreTimeoutExceptionキャプチャすることができます
     * / 
    パブリックブールSETNX(Storekeyキー、オブジェクトの値を、int型 expireInSecondsを)。

 質問です:方法:

入手トークン
ロックメソッドを使用します。
(redisStoreClient.setnx(ロック、「ロック場合 」、LOCK_EXPIRE_SECONDS)){ 
このメソッドは存在しないとキーがすでに存在する場合のキーは、正常に追加された場合、falseを返す
と言って:追加する唯一の鍵は、そうでない場合は破棄され、唯一のトークンを取得成功し、防止します南京のサーバーの問題。

おすすめ

転載: www.cnblogs.com/aspirant/p/11082985.html