Говоря о распределенной трассировке ссылок

Архитектура

отслеживание ссылок

В конечном счете, отслеживание ссылок — это просто концепция и стратегия, проще говоря, это способность передавать определенную прозрачную информацию между двумя вызовами ассоциации. С точки зрения проектирования компонентов нас на самом деле интересуют следующие особенности:

  • PAN с: сферу того, что доступно в диапазоне, нет случая, когда недоступно
  • Полнота: считается ли дизайн модели данных достаточно всеобъемлющим, некоторые должны быть, а некоторые не следует выбрасывать.
  • Стоимость: Стоимость и риск реализации, сложность доступа. Существует еще много разных стратегий посадки на план реализации, но в целом стратегий три.

Решение на основе определенного языка

Типичным примером является система Java.Вообще говоря, Java является компилируемым языком, но он гордится реализацией виртуальных машин и байт-кодов.Java на самом деле обладает характеристиками динамического языка.

Основная идея этого типа реализации заключается в использовании java-агента для перехвата процесса загрузки определенного класса и добавлении пользовательского кода в процесс загрузки определенного класса для достижения возможности трассировки.

Основным недостатком этого типа решения является то, что его можно использовать только на Java, но поскольку реализация стека технологий Java доступна без каких-либо ограничений, это очень эффективно для компаний со стеком технологий Java. Стоимость доступа также очень низкая, пока параметры указаны в команде запуска, очень удобно развертывать скрипты или создавать образы. Еще одним недостатком является то, что изменение самого байт-кода по-прежнему сопряжено с определенными рисками. Тем не менее, общая стабильность по-прежнему гарантируется.skywalking

Внедрение на основе спецификации кодирования в организации

Не все компании используют java внутри себя, а другие языки не изменили работу с байткодом или считают этот метод слишком грубым, что мне делать?

Основная идея в этом случае состоит в том, чтобы абстрагироваться от концепции уровня протокола, чтобы реализация каждого компонента поддерживала внутреннюю реализацию отслеживания ссылок, а сбор информации компонента журнала трассировки также выполнялся этим компонентом. Если деловая сторона имеет особые потребности в доступе к системе отслеживания ссылок, она также должна иметь возможность взаимодействовать с отслеживанием в соответствии с тем же соглашением. Кроме того, также учитывается необходимость совместимости с различными компонентами с открытым исходным кодом.

В этом случае очень важен дизайн уровня протокола.Это план, который должен быть согласован и понят всеми сторонами.Очень важна полнота самого протокола. В настоящее время наиболее известной является спецификация opentracing, которую в принципе можно считать стандартом де-факто в области отслеживания ссылок.

С моей личной точки зрения, этот метод является лучшей стратегией, а также необходимо внедрять стандартизированные спецификации программирования внутри крупных компаний, но это тоже палка о двух концах.Внедрение трассировки зависит от степени стандартизации, т.к. ссылка Такого рода вещи не могут достичь эффекта отслеживания ссылок, если они прерываются один раз.

Другая проблема заключается в том, что даже стандартизация ограничена: например, межпотоковую передачу информации в основном сложно осуществить внутри компании. Функция, которая получается из этого, на самом деле не так проста и эффективна, как расширение байт-кода.jaeger,CAT,SOFATracer,zipkin,dapper

решения на основе сетки

Конечно, с развитием контейнеризации и сервисной сетки в последние годы решения на основе сервисной сетки также могут выполнять отслеживание ссылок. Перехватив трафик через sidecare, можно построить систему отслеживания ссылок, не зависящую от конкретных языков или rpc.С точки зрения модели это действительно более идеальная модель, но как сделать так, чтобы исполняющая программа также воспринимала отслеживание ссылок также является проблемой.В то же время, различные схемы сетки все еще находятся в стадии исследования и практики на данный момент, и нет идеального решения.jaeger

Дизайн модели и протокола

модель данных

Большинство существующих моделей отслеживания ссылок относятся к реализации dapper, и спецификация opentracing также оказывает большое влияние на дизайн модели. Семантика opentracing. Большая часть следующего выдержки из этих двух частей

Проще говоря, внешний вызов может быть выполнен комбинацией нескольких внутренних запросов.Этот процесс можно описать как дерево, и каждый вызов определяется как диапазон. Весь вызов можно назвать трассировкой и идентифицировать по уникальному идентификатору.

Промежуток — это наименьшая единица, из которой состоит дерево вызовов. Обычно включает следующие части, обычно идентифицируемые уникальным идентификатором:

  • Имя операции, обычно шаблон, например имя вызывающего метода, например URL-адрес и т. д.
  • Время начала и окончания.
  • 0 или более тегов, ключ представляет собой строку, значение, такое как IP-адрес, имя приложения, имя данных, URL-адрес и т. д.
  • 0 или более журналов, таких как коды ошибок, стеки вызовов и сообщения о времени.
  • 0 или более ссылок на диапазоны (ChildOf, FollowsFrom)
  • SpanContext, (traceid, spanid, sampleFlag, Baggage) — это концепция или что-то на уровне интерфейса. Объекты, которые можно использовать для сериализации и десериализации или предоставления тонких API-интерфейсов для ПО промежуточного слоя и бизнес-программ, по своей сути неизменяемы. Багаж может прозрачно передавать кв пользователя.
Causal relationships between Spans in a single Trace

        [Span A]  ←←←(the root span)
            |
     +------+------+
     |             |
 [Span B]      [Span C] ←←←(Span C is a `ChildOf` Span A)
     |             |
 [Span D]      +---+-------+
               |           |
           [Span E]    [Span F] >>> [Span G] >>> [Span H]
                                       ↑
                                       ↑
                         (Span G `FollowsFrom` Span F)

В приведенном выше дереве вызовов отслеживания ссылок более интуитивно понятно, и нужно объяснить только два места:

связь между пролетами

Одна ссылка в спане.На самом деле я думаю это приложение лучше понимает разницу.Большинство реализаций вряд ли найдут ссылки на все подспаны,или в этом нет необходимости. В большинстве случаев для построения используется понятие parent-span-id. ссылочный тип,

  • ChildOf в основном используется в синхронных сценариях, в которых дочерний диапазон должен возвращаться до конца родительского диапазона.
  • FollowsFrom в основном относится к некоторым асинхронным сценариям.В этом случае дочерний диапазон и родительский диапазон связаны только логически, но нет никакой связи во времени.В построении ссылки нет проблем, но в некоторой обработке данных это будет быть более хлопотным в сцене. Например, нельзя определить, когда заканчивается ссылка?

На самом деле, здесь я действительно больше думаю о том, как определить рамки размаха обсуждения, но на мой личный взгляд и не в пользу асинхронных сцен, связанных между собой. В основном на основе двух моментов для рассмотрения

  • Во-первых, трассировка часто используется для анализа производительности или анализа зависимостей и др. В этих двух типичных сценариях нет особого смысла соединять асинхронные сценарии последовательно, но это не способствует последующей работе по анализу данных.

  • Другая причина заключается в том, что даже если вы не используете саму структуру spanid, это не означает, что связанная с ней информация будет потеряна, потому что сама трассировка имеет возможность прозрачно передавать информацию. Для прозрачной передачи, даже если сам канал больше не находится под той же самой трассировкой, информация все еще может быть прозрачно передана.

Принцип прозрачной передачи

Суть прозрачной передачи заключается в завершении построения пространственного контекста между двумя контекстами. В общем, нужно сделать 2 вещи, одна — передать spanContext для перестроения спана максимально ненавязчивым способом. Другой — создать новый диапазон в spanwapper, созданном текущим контекстом, и поместить его на вершину стека.Конечно, вы также можете выбрать, создавать ли новый диапазон в зависимости от ситуации. На рисунке ниже показан пример поперечного прохода резьбы.

В сценарии прозрачной передачи параметры являются необязательными. В большинстве сценариев трассировка предназначена только для обработки запросов между средами выполнения, а внутренний перекрестный поток не создает диапазон данных. В этом случае новый диапазон не создается. Вызов rpc создаст новый диапазон.

Составление данных журнала Span, прозрачная передача и сбор

Еще одна вещь, которую следует обсудить, — это SpanContext: на самом деле SpanContext имеет разные концепции в разных сценариях. Здесь это больше относится к структурной части, используемой для нисходящей линии восстановления, и к параметрам, которые необходимо передавать прозрачно. По приведенному выше содержанию легко понять, что пролет — это на самом деле два бревна, которые должны быть построены пиром для завершения построения. Эти два журнала будут собираться соответствующими экземплярами и загружаться отдельно.Только небольшое количество параметров будет прозрачно передаваться в нисходящий поток вместе с rpc и другими носителями для восстановления связи или прозрачной передачи параметров.Как правило, прозрачная передача параметров делится на 3 части:

  • Сервисные параметры, которые необходимо передавать прозрачно: например, идентификатор измерения давления, logId и т. д. Эти параметры необходимо передавать независимо от сценария.
  • Параметры для построения спана: На самом деле нужны только три: traceId, spanId и sample.Эти параметры будут передаваться или не передаваться в зависимости от разных сценариев.Вообще говоря, он не передается в синхронных сценариях и асинхронных сценариях. Если он не передан, нисходящий поток обычно создает новый spanId и traceid.В настоящее время журналы, которые могут создать диапазон, являются только односторонними журналами.
  • Параметры, используемые для обмена информацией: Помимо указанных выше параметров, по внеполосным каналам могут передаваться и другие параметры, в большинстве случаев они передаются с использованием стека технологий, аналогичного ELK. В частности, на самом деле существуют разные стратегии реализации прозрачной передачи, как показано на следующем рисунке.

  • Одно из решений состоит в том, чтобы передавать в запрос как бизнес-информацию, так и информацию о построении промежутка, а возвращаемый результат нисходящего потока также передает ту же информацию обратно. Преимущество этой модели в том, что концепции и модели относительно ясны. Но вопрос в том, нужно ли по-прежнему распечатывать исходную информацию при выполнении запроса? Однако в настоящее время он не печатается в установленный срок, и после получения ответа на информацию запроса необходимо выполнить слияние. Или распечатайте журнал дважды и выполните одно слияние данных на уровне хранилища.
  • Другим решением является сохранение временных данных в стеке переменной текущего потока, а затем извлечение текущего объекта из стека после возврата запроса. Добавьте параметры запроса к объекту. Однако этот метод не может обрабатывать сценарии асинхронного обратного вызова.
  • Последний — асинхронно реконструировать пролет. Параметр выборки здесь особенный.Большинство систем отслеживания ссылок нуждаются в выборке.Режим выборки – head-based, то есть выборка производится после выборки узлов. Это приводит к тому, что даже если traceI и spanid не передаются в некоторых асинхронных сценариях, необходимо передать образец.

Разделение модулей и границы дизайна

Разделение системного модуля

Здесь описан общий тип конструкции модуля отслеживания распределенных ссылок, и разные системы могут иметь компромиссы в разных местах. Но в целом следуйте

Разделение и реализация клиентских функций

  • агент - модуль перекодированного упакованного кода для javaagent
    • улучшение кода преобразования
    • Код разумного агента загрузчика классов для предотвращения загрязнения класса
    • static-config, статическая конфигурация для логики перехвата и статическая конфигурация
  • плагин - логика на конкретном бизнес-уровне
  • клиент-компонент pom зависимость
    • Конструкции интерфейса opentracing span
    • процессор, общая логика обработки
    • weavepoint, определение типа точки улучшения используется для определения области действия
    • динамическая конфигурация. Используется для получения динамической конфигурации
    • журнал, журнал печати
    • утилита, набор инструментов
  • зависимость модели основных данных

Дизайн классов и интерфейсов

Существует множество форм реализации отслеживания ссылок.Насколько я понимаю, требуются два уровня абстракции, и первый уровень — это уровень улучшения. Конкретная реализация модуля кода по-прежнему разделена на множество интересных частей.Модуль кода разделен на несколько частей.

На уровне кода фактически есть два уровня абстракции.

  • Уровень абстракции предназначен для точек улучшения или точек имплантации. Поскольку входы разных носителей различны, wapper представляет собой унифицированную обработку точек улучшения, которая используется для закрытия единого кода. Уровень wapper будет оценивать тип ввода текущего кода и выбирать для обработки другой AbsctrctWeaveProcess. Код может быть разработанные абстрактные шаблоны кода (базовые классы на стороне клиента и службы). Различные точки имплантации расширены на интерфейсы, предоставляемые базовым кодом.
  • Вообще говоря, приведенный выше код может гарантировать базовую функцию отслеживания ссылок. Тем не менее, часто существует множество бизнес-функций, которые необходимо обслуживать внутри компании. Например, измерение давления, прозрачная передача пользовательских параметров, окраска среды, logId и т. д. Эти функции часто имеют унифицированный уровень бизнес-абстракции и нуждаются в повторном использовании в различных точках расширения, поэтому более разумно абстрагировать уровень подключаемых модулей.

интересные детали дизайна

Trace-id vs log-id

Является ли логид трассировкой? Какая разница между двумя? Строго говоря, log-id не является trace-id, но может им быть. По сути, трассировка обеспечивает возможность прозрачной передачи информации, а logid часто используется для объединения информации журнала. Поэтому в большинстве сценариев logid прозрачно передается между системами благодаря возможности прозрачной передачи трассировки. Он часто хранится в концепции threadlocal или контекст внутри системы. В дополнение к первому разу мы также обсудили интересную проблему до этого — конкатенацию в асинхронных сценариях. По предыдущему содержимому мы фактически обсудили, что хотя саму трассировку можно использовать в асинхронных сценариях из-за ограничения времени начала и окончания, это доставит много хлопот при анализе информации.На практике я вообще-то предпочитаю определять traceid в области синхронного вызова. Внутри, в асинхронных сценариях, таких как асинхронный RPC или сценарии очереди сообщений, реконструируйте logId.

Java-агент и улучшение байт-кода

Существует также проблема, которая здесь не объясняется, заключается в том, как добиться улучшения байт-кода, основной принцип заключается в использовании java-агента. Хотя java является компилируемым языком, из-за наличия jvm и загрузчика классов у java есть определенные динамические характеристики. Фактическая логика работы java на самом деле зависит от байт-кода в jvm. Например, аннотации управления транзакциями, которые пропускают большинство javaers, по существу отмечают определенные методы или переменные-члены и генерируют прокси-класс во время выполнения процесса.Добавьте немного управления транзакциями. шаблоны на основе оригинального метода. Будь то создание нового прокси-класса или изменение байт-кода исходного класса, можно реализовать динамический прокси. Вернемся к сценарию использования трассировки.На самом деле мы тоже надеемся улучшить байт-код.Теоретически этого можно добиться и созданием динамических агентов на основе загрузки пользовательского класса,но основная проблема в том,что нет возможности контролировать все классы.Загрузчик, по сути, трассировка надеется реализовать wapper на методе и не заботится о том, какой конкретный класс загружается. Сама Java предоставляет механизм java-агента, который может перехватывать все процессы загрузки классов, либо перегружать бэкдор класса во время работы, что явно больше подходит для нашего сценария. В использовании, пока соответствующий интерфейс реализован и упакован в банку. java-agent предоставляет два способа: первый — запустить его одновременно с jvm-runtime в качестве параметра запуска. Или после запуска экземпляра jvm он запускается как процесс очереди и присоединяется к процессу jvm. Способ реализации кода здесь подробно не обсуждается, потому что примеров в интернете много, а то, о чем я хочу рассказать, это набор общих методов проектирования, используемых java-агентом, что также очень полезно для понимания других конструкции с открытым исходным кодом.

Типичный модуль, связанный с java-агентом, во многих случаях включает вышеуказанные части.

  • Первый — агент-вход. Вот интерфейс, который реализует java-агент, который похож на основной метод, и в нем разворачивается основная логика.
  • На самом деле это часть, которая взаимодействует с внешними интерфейсами, которые могут предоставлять наблюдаемую и действующую запись, такую ​​как https-сервер или клиент etcd/zk.
  • Основной функцией многих java-агентов является усиление байт-кода, это на самом деле очень опасная операция, которая эквивалентна логике работы кода без остановки, поэтому некоторые spi-интерфейсы обычно определены, а точки улучшения ограничены некоторые В рамках этого, путем независимой компиляции некоторых jar-файлов для изменения загрузки интерфейса, помимо соображений безопасности, также предполагается рассмотреть возможность разделения кода. Этот процесс немного похож на то, когда мы пишем службу API, мы сначала поместим URL-адрес, а затем напишем этот URL-адрес, чтобы добиться того же.
  • Другой модуль сценария — автономный загрузчик классов. Поскольку javagent часто запускается в предварительном режиме, основной метод еще не запущен.Если ссылаются на множество классов из-за вводной зависимости, загрязненный класс может быть загружен, когда последующее приложение запускается нормально. Поэтому большинство из них напишет загрузчик классов для независимой загрузки классов, используемых агентом, чтобы избежать проблем с загрязнением. Эта загрузка класса обычно не относится к родительской модели делегирования.

Область применения java-агента на самом деле очень широка, вот несколько примеров;

  • Реализация трассировки с открытым исходным кодом:skywalking.apache.org/
  • Хаос Инженерия:GitHub.com/Alibaba/JVM...,GitHub.com/ultrasonic-spicy-…
  • инструмент диагностики Java-анализа:GitHub.com/Alibaba/art…Образец основания головы и образец основания хвоста Каждый RPC будет создавать 2 журнала. Без выборки количество журналов будет очень большим. Большинство журналов трассировки являются выборочными, а частота выборки очень низкая, в основном от 1 до 5%. Однако это не влияет на функцию трассировки.Как упоминалось ранее, выборка включает только регистрацию и загрузку журналов и не влияет на генерацию спанов и прозрачную передачу параметров, а влияет только на то, загружаются ли сгенерированные спаны. Сама по себе выборка тоже имеет интересный момент.Большинство трасс являются head-base, то есть только корневой узел имеет право решать использовать выборку или нет.Последующие узлы определяют, следует ли производить выборку в соответствии с флагом выборки, переданным от апстрима.

Типичные сценарии применения

Запрос окрашивания (среда маршрутизации)

Сначала представим концепцию изоляции среды: большинство режимов разработки основаны на gifflow. Если есть только один набор сред, возникнет проблема слияния нескольких кодов.Если вы создаете несколько наборов сред, стоимость будет очень высокой (например, независимые базы данных, Nginx, реестр, Redis и большое количество зависимые службы), то есть. Разве нет способа создать несколько сред, не беспокоясь о проблемах с продуктом?

Решение раскраски среды заключается в том, что трассировка анализирует информацию о среде входа и выхода при каждом запросе промежуточного программного обеспечения и прозрачно передает ее в качестве параметра, а каждый компонент промежуточного программного обеспечения взаимодействует с информацией для маршрутизации трассировки в соответствующий кластер: простой пример: следует:

Основная идея заключается в том, что все кластеры имеют набор эталонных сред, обычно развернута основная ветка, а изменения, связанные с этой веткой, развертывают набор функциональных кластеров. . Все общие компоненты используют один и тот же набор, например Nginx, реестр, базу данных, кластер kafka и т. д. Однако ресурсы, используемые приложением, будут несколько отличаться: например, в реестре есть информация о среде кластера, а rds может создать теневую таблицу с суффиксом имени среды. В Kafka есть тема, соответствующая суффиксу имени среды. Когда пользователь запрашивает, используется то же имя домена, но заголовок с именем среды прилагается.Когда приложение примет запрос, оно проанализирует заголовок и поместит информацию о среде входа в baaage, и информация будет загружена вместе с связь.

Для RPC клиент предпочтительно выбирает кластер определенной подсреды в соответствии с информацией о среде при выполнении маршрутизации. Если нет, он вызывает тестовую среду. Приложение в эталонной среде также может предпочтительно вызывать подсреду в соответствии с тем же правилам при вызове. Даже если вызов проходит через промежуточное ПО, такое как очереди, передаваемое сообщение также сопровождается информацией об окружающей среде, и трассировка также может анализировать правила маршрутизации на основе информации и передавать их прозрачно. Однако, чтобы предотвратить использование сообщений приложением в тестовой среде, по-прежнему необходимо создать тему для конкретной подсреды.

Другие сценарии применения

  • стресс тест
  • многоуровневое приложение
  • Поиск проблемы

Официальный аккаунт WeChat: Волшебный программист


Принимайте внутренние push-уведомления от производителей первого уровня (Microsoft, Ali, Toutiao, NetEase), за подробностями обращайтесь в официальный аккаунт или на почту Andrewzhch@gmail.com