задний план
Наиболее часто используемый метод разработки и устранения неполадок системы — просмотр системных журналов.В распределенной среде ELK обычно используется для единообразного сбора журналов.Однако использовать журналы для обнаружения проблем, когда параллелизм большой, сложнее.Давайте посмотрим на картинку ниже:
На рисунке выше пользователь запрашивает URL-адрес, и вся ссылка показана на рисунке. Каждый уровень обработки будет генерировать журналы. Как мы можем связать эти журналы вместе, чтобы сформировать журнал полного пути запроса.
В существующей системе сложно отфильтровать все релевантные логи указанного запроса, потому что также выводится и проходит через них большое количество логов других пользователей/других потоков. ** Тогда как мы с этим справимся?
Решения
мы можем поставитьПолучите уникальный идентификатор для каждого запроса,тогда мыВы можете использовать уникальный идентификатор для каждого запроса при печати журнала, и чтоУникальный идентификатор должен быть передан нижестоящим службам.,Этот уникальный идентификатор также включается, когда нижестоящая служба печатает журнал., поэтому приятно отслеживать все ссылки, отображаемые в логе.
Каков план технической реализации?мы должны стараться изо всех силБез вмешательства в код,использоватьИдентификатор traceId добавляется в шаблон журнала механизма MDC Logback и имеет значение %X{traceId}..
Что такое МДК
MDC (сопоставленный диагностический контекст, сопоставленный контекст отладки)Это функция, предоставляемая log4j и logback для облегчения ведения журнала в многопоточных условиях..MDC можно рассматривать как карту, привязанную к текущему потоку.,МогуДобавьте к нему пары ключ-значение.
Доступ к содержимому, содержащемуся в MDC, можно получить с помощью кода, выполняющегося в том же потоке.. Дочерние потоки текущего потока наследуют содержимое MDC в своем родительском потоке. Когда требуется регистрация,Просто получите необходимую информацию от MDC. Содержимое MDC сохраняется программой при необходимости. Для веб-приложения эти данные обычно хранятся в самом начале обрабатываемого запроса.
Реализация схемы
Поскольку MDC внутренне используетThreadLocal, поэтому действителен только этот поток, значение в дочернем потоке и подчиненном сервисе MDC будет потеряно; поэтомуОсновная сложность решения заключается в решении проблемы переноса стоимости, который в основном включает в себя следующие части:
-
Как данные MDC в шлюзе API передаются нижестоящим службам
-
Как служба получает данные и как передавать их при вызове других удаленных служб
-
Как передать его дочернему потоку в случае асинхронного (пула потоков)
Изменить шаблон журнала
Добавьте этот флаг в формат журнала файла конфигурации logback.
Шлюз добавить фильтр
Этот фильтр определяет, как шлюз передает данные MDC нижестоящим службам:
Создайте traceId и передайте его нижестоящему сервису через заголовок
В приведенном выше коде есть MDC, принадлежащий org.slf4j.MDC, а следующее значение константы:
/**
* 日志链路追踪id信息头
*/
String TRACE_ID_HEADER = "x-traceId-header";
/**
* 日志链路追踪id日志标志
*/
String LOG_TRACE_ID = "traceId";
Добавить перехватчик spring в нижестоящие сервисы
Получите и сохраните значение traceId:
Добавить ложный перехватчик к нижестоящим сервисам
Продолжайте передавать значение traceId текущей службы нижестоящей службе:
Решить проблему передачи потоков родитель-потомок
В основном для бизнеса будет использоваться пул потоков (асинхронная, параллельная обработка), а сама весна также имеет аннотацию @Async для использования пула потоков, для решения этой проблемы требуются следующие два шага:
Переопределить LogbackMDCAdapter logback
Поскольку реализация logback MDC использует ThreadLocal внутри, она не может передавать подпотоки, поэтому ее необходимо переписать и заменить на TransmittableThreadLocal Ali.
TransmittableThreadLocal является открытым исходным кодом Alibaba., заРасширение InheritableThreadLocal для устранения проблемы «передачи ThreadLocal при использовании таких компонентов, как пулы потоков, которые кэшируют потоки». Если вы хотите, чтобы TransmittableThreadLocal передавался между пулом потоков и основным потоком, вам нужно использовать его с TtlRunnable и TtlCallable.
Остальной код такой же, как и в ch.qos.logback.classic.util.LogbackMDCAdapter, только вместо этого вызовите переменную copyOnInheritThreadLocal.
Класс TtlMDCAdapterInitializerИспользуется для загрузки собственной реализации mdcAdapter при запуске программы:
Реализация расширенного пула потоков
Добавлены расширения TtlRunnable и TtlCallable:
Тест сценария
Код теста выглядит следующим образом:
log.info("测试")
@Async
public void test(){
log.info("测试1")
}
userService.findByUserName("gu");
Журнал, напечатанный шлюзом API
Совокупные журналы ELK запрашивают весь журнал ссылок по traceId.
Когда в системе возникает исключение, вы можете напрямую запросить в центре журнала всю информацию журнала запроса через значение traceId журнала исключений, как показано на следующем рисунке:
Суммировать
На данный момент отслеживание распределенного журнала завершено, поэтому очень полезно проверить ссылку на журнал всего микросервиса, спасибо! ! !
Перепечатано в:Tickets.WeChat.QQ.com/Yes/XO топор UN do OD…
пасхальные яйца
Приглашаю всех обратить внимание на мой публичный аккаунт [A Feng's Architecture Notes], Вопросы расширенного интервью на Java, необходимые для интервью в 2020 году, обобщают некоторые примечания к учебным документам и анализ интервью, всего 2000 страниц, статьи будут обновлены в нем, а собранная информация будет возвращена в [2020] для получения !