フィールドの同期


フィールドの同期-開発
以前やったログトラッカーに問題があります.
トランザクションIDを照合するために、パラメータをオーバーしましたTraceIdこの移行方式は論理に参加する必要があるため、悪い方法です.TraceIdをパラメータに変換せずにこの問題を解決する方法はありますか?
LogTrace

FieldLogTrace
package hello.advanced.trace.logtrace;

import hello.advanced.trace.TraceId;
import hello.advanced.trace.TraceStatus;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class FieldLogTrace implements LogTrace{

    private static final String START_PREFIX = "-->";
    private static final String COMPLETE_PREFIX = "<--";
    private static final String EX_PREFIX = "<X-";

    private TraceId traceIdHolder; //traceId 동기화, 동시성 이슈 발생

    @Override
    public TraceStatus begin(String message) {
        syncTraceId();
        TraceId traceId = traceIdHolder;
        Long startTimeMs = System.currentTimeMillis();
        log.info("[{}] {}{}", traceId.getId(),
                addSpace(START_PREFIX, traceId.getLevel()), message);
        return new TraceStatus(traceId, startTimeMs, message);
    }
    
    private void syncTraceId() {
        if (traceIdHolder == null) {
            traceIdHolder = new TraceId();
        } else {
            traceIdHolder = traceIdHolder.createNextId();
        }
    }

    @Override
    public void end(TraceStatus status) {
        complete(status, null);
    }

    @Override
    public void exception(TraceStatus status, Exception e) {
        complete(status, e);
    }

    private void complete(TraceStatus status, Exception e) {
        Long stopTimeMs = System.currentTimeMillis();
        long resultTimeMs = stopTimeMs - status.getStartTimeMs();
        TraceId traceId = status.getTraceId();
        if (e == null) {
            log.info("[{}] {}{} time={}ms", traceId.getId(),
                    addSpace(COMPLETE_PREFIX, traceId.getLevel()), status.getMessage(),
                    resultTimeMs);
        } else {
            log.info("[{}] {}{} time={}ms ex={}", traceId.getId(),
                    addSpace(EX_PREFIX, traceId.getLevel()), status.getMessage(), resultTimeMs,
                    e.toString());
        }
        
        releaseTraceId();
    }

    private void releaseTraceId() {
        if (traceIdHolder.isFirstLevel()) {
            traceIdHolder = null; //destroy
        } else {
            traceIdHolder = traceIdHolder.createPreviousId();
        }
    }

    private static String addSpace(String prefix, int level) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < level; i++) {
            sb.append( (i == level - 1) ? "|" + prefix : "|   ");
        }
        return sb.toString();
    }

}
FieldLogTraceHelloTraceV2と同様の機能を有する.
違いは、TraceIdFieldLogTracetraceIdHolderで管理されている点です.syncTraceId()releaseTraceId()syncTraceId()
  • begin()中呼び出し
  • 初回コールが再生成されるTraceId
  • またはTraceId同期levelひとつ追加
  • releaseTraceId()
  • end->complete()中呼び出し
  • 1段目ならTraceIdクリア
  • またはTraceId通機化level1個減
  • [c80f5dbb] OrderController.request() //syncTraceId(): 최초 호출 level=0
    [c80f5dbb] |-->OrderService.orderItem() //syncTraceId(): 직전 로그 있음 level=1 증가
    [c80f5dbb] | |-->OrderRepository.save() //syncTraceId(): 직전 로그 있음 level=2 증가
    [c80f5dbb] | |<--OrderRepository.save() time=1005ms //releaseTraceId(): level=2->1 감소
    [c80f5dbb] |<--OrderService.orderItem() time=1014ms //releaseTraceId(): level=1->0 감소
    [c80f5dbb] OrderController.request() time=1017ms //releaseTraceId(): level==0, traceId 제거
    テスト


    よく撮れたTraceIdをパラメータにする必要がなく、出力が良好であることが判明しました.
    フィールドの同期-適用
    せいぎょそうち

    サービス

    研究する


    すべてが順調であることが確認できます.
    しかし、この方法では同期性の問題が発生します.
    どうじせいもんだい

    上の彼はsleepだから1回目の論理変換に1秒かかる
    これは1秒に2回接続すると表示されるログです.
    取引IDを区別できません.
    コントローラ->サービス->リポジトリ->コントローラ
    このように等級も違います.

    うん、でも猫支援のThreedはよく区別されています.
    すなわち,同期性の問題が発生した.
    同期の問題-サンプルコード
    FieldService

    FieldServiceTest

    実行結果
    sleep乙2秒を与えたためuserA論理が完了するまで静止していたがuserBに移行し、動作が正常であることが確認できる.
    どうきはっせい

    実行結果

    A Threedが保存されているuserA、1秒後に照会nameStoreそれ以前に、B Threadが格納されていたuserBクエリーnameStoreの場合、userBクエリーの現象が発生します.
    どうじせいもんだい
    このように、複数のスレッドが同じインスタンスのフィールド値を同時に変更した場合に発生する問題を同期性問題と呼ぶ.この同時性の問題は,複数のスレッドが同じインスタンスのフィールドにアクセスする必要があるためであり,トラフィックが少ない場合,確率的にあまりよく表現されず,トラフィックがますます多くなるほどよく見られる.
    特に、スプリングシートのようにモノトーンオブジェクトのフィールドを変更して使用する場合は、これらの同期性の問題に注意してください.
    では、モノトーンオブジェクトフィールドを書き込みながら同期の問題を解決するには、次の手順に従います.
    このときはThreedローカルを使用します.