نسخه آنلاین در حال بارگذاری زمان... تهران: ۲۶°C
۲۸ کاربر آنلاین

PNo.30Light

نشریه تخصصی هوش مصنوعی، سیستم‌های سرور و مهندسی داده

تازه ترین‌ها
زیرساخت و سرور
زمان مطالعه: ۲۶ دقیقه ۰ بازدید

Jaeger: Distributed Tracing برای Microservices — از Uber تا OpenTelemetry و v2

نویسنده: تحریریه فنی P30Light
Jaeger: Distributed Tracing برای Microservices — از Uber تا OpenTelemetry و v2
✦ خلاصه نکات کلیدی مقاله
  • Jaeger = پلتفرم open source distributed tracing — CNCF Graduated؛ مسیر درخواست را بین سرویس‌ها وصل می‌کند.
  • Jaeger v2 = توزیع سفارشی OpenTelemetry Collector با نقش‌های collector / query / all-in-one و پشتیبانی بومی OTLP.
  • Storage: Cassandra، ES/OpenSearch، Badger، و از v2.18+ ClickHouse بومی (alpha) برای حجم و فشرده‌سازی بالا.

در معماری microservice، یک درخواست کاربر ممکن است از API Gateway به ده سرویس، دو صف، یک cache و یک دیتابیس برود. وقتی latency بالا می‌رود یا error می‌آید، log خام و metric میانگین کافی نیست — باید مسیر دقیق همان درخواست را ببینید.

Jaeger برای همین ساخته شد:

open source, distributed tracing platform — Monitor and troubleshoot workflows in complex distributed systems.

یعنی متصل کردن نقطه‌ها بین سرویس‌های پراکنده: پیدا کردن bottleneck، ریشهٔ خطا، و وابستگی سرویس‌ها — با مقیاس ابری و بدون قفل vendor.

CNCF Graduated — یکی از اولین پروژه‌های graduated بنیاد. خاستگاه: Uber (اهدا به CNCF). لایسنس: Apache 2.0. سایت: jaegertracing.io · Docs: docs · Repo: github.com/jaegertracing/jaeger


مشکل: بدون Trace، Blind Debugging

بدون tracing:
  Service A ──?──► B ──?──► C
  metric: p99 بالا — کجا؟
  log: خطای timeout در C — چرا A کند بود؟

با Jaeger:
  Trace ID = abc123
  A (12ms) → B (80ms) → C (410ms) ← bottleneck
  هر span: tags، logs، status، parent/child
معیارفقط Logفقط MetricDistributed Tracing (Jaeger)
مسیر یک درخواستسختنهبله — Trace
Latency بین سرویس‌هاحدسمیانگینper-span / waterfall
Dependency mapدستیمحدوداز دادهٔ واقعی
Root cause در cascadeزمان‌برگم‌کنندههدف اصلی
هزینهٔ volumeبالامتوسطنیاز به sampling

Tracing جایگزین log یا metric نیست — ستون سوم observability کنار آن‌هاست. برای log یکپارچه ببینید: Fluentd. برای mesh و proxy: Istio و Envoy.


Jaeger چیست؟

طبق جاegertracing.io و Features:

  • پلتفرم distributed tracing برای مانیتور و عیب‌یابی workflowهای توزیع‌شده
  • طراحی‌شده برای high scalability (مثلاً استقرار Uber: میلیاردها span در روز)
  • Cloud Native: image کانتینر، binary، Operator و Helm برای Kubernetes
  • دریافت داده با OTLP (پروتکل استاندارد OpenTelemetry) به‌علاوه پروتکل‌های legacy Jaeger و Zipkin
  • UI مدرن (React) برای جستجوی trace، timeline، dependency graph و SPM
  • Sampling سر/دم برای کنترل سربار و هزینهٔ storage

مفاهیم پایه

مفهوممعنی
Traceکل مسیر یک درخواست end-to-end (گراف spanها)
Spanیک واحد کار (مثلاً HTTP call، DB query) با زمان شروع/پایان
Span contexttrace_id، span_id، flags — در headerها propagate می‌شود
Tags / Attributesمتادیتای کلید-مقدار (http.status_code, db.statement, …)
Baggageدادهٔ contextual که همراه درخواست بین سرویس‌ها سفر می‌کند
Samplingتصمیم اینکه کدام trace ذخیره شود (کاهش هزینه و سربار)

مدل داده در UI همچنان نزدیک OpenTracing است (DAG با span references، نه فقط درخت ساده)، در حالی که ingestion مدرن روی OTLP متمرکز است.


تاریخچهٔ کوتاه: از OpenTracing تا Jaeger v2

دورهتحول
UberJaeger برای scale داخلی؛ بعد اهدا به CNCF
OpenTracingاستاندارد instrumentation اولیه که Jaeger روی آن شکل گرفت
OpenTelemetryادغام OpenTracing + OpenCensus؛ SDK و پروتکل واحد
OTLP در Jaegerاز حدود v1.35 دریافت بومی OTLP
Jaeger v2بازسازی روی OpenTelemetry Collector — یک binary، نقش‌های مختلف، YAML pipeline
v2.18+پشتیبانی native ClickHouse به‌عنوان storage (alpha)

پیام جامعه امروز: instrument کنید با OpenTelemetry SDK؛ backend می‌تواند Jaeger باشد. exporterهای بومی Jaeger در SDKها به‌تدریج به نفع OTLP کنار می‌روند.


معماری Jaeger v2

Jaeger v2 یک binary انعطاف‌پذیر است که با config به نقش‌های مختلف درمی‌آید:

نقشکار
collectorدریافت trace از appها و نوشتن به storage
queryAPI + UI برای جستجو و نمایش
ingesterخواندن از Kafka و نوشتن به storage
all-in-onecollector + query در یک process
agentsidecar/host forwarder — توصیهٔ رسمی: به‌جای آن از OpenTelemetry Collector استفاده کنید
Apps (OTel SDK / Zipkin / legacy Jaeger)
        │  OTLP :4317/:4318  (یا Zipkin :9411)

┌───────────────────┐     اختیاری      ┌─────────────┐
│ Jaeger collector  │ ───────────────► │    Kafka    │
│  (+ processors)   │                  └──────┬──────┘
└─────────┬─────────┘                         │
          │ direct                            ▼
          │                          ┌─────────────┐
          ▼                          │  ingester   │
┌───────────────────┐                └──────┬──────┘
│ Storage backend   │ ◄─────────────────────┘
│ ES / Cassandra /  │
│ OpenSearch /      │
│ ClickHouse /      │
│ Badger / memory   │
└─────────┬─────────┘

┌───────────────────┐
│ query + Jaeger UI │  :16686
└───────────────────┘

دو الگوی استقرار مقیاس‌پذیر

  1. Direct-to-storage — collector مستقیم به DB می‌نویسد. ساده؛ storage باید peak را تحمل کند.
  2. Via Kafka — collector به Kafka export می‌کند؛ ingester می‌خواند و به storage می‌نویسد. بافر پایدار در برابر spike و outage کوتاه storage.

all-in-one چه وقت؟

حالتمناسب
all-in-one + in-memorydev / demo — داده با restart از بین می‌رود
all-in-one + Badgerproduction کوچک، تک‌نود — بدون scale افقی
collector / query جدا + storage خارجیproduction واقعی — scale جدا برای write و read

جزئیات: Architecture.


Jaeger روی OpenTelemetry Collector

Jaeger v2 عملاً یک توزیع سفارشی از OpenTelemetry Collector است با:

  • کامپوننت‌های upstream (OTLP receiver، batch، attributes، …)
  • contrib (Kafka، tail sampling، …)
  • کامپوننت‌های خود Jaeger: Storage Extension/Exporter، Query Extension، Adaptive Sampling، Remote Sampling

می‌توانید با OpenTelemetry Collector Builder (ocb) توزیع سفارشی بسازید.

Receivers مهم

Receiverکاربرد
OTLPمسیر پیشنهادی امروز
JaegergRPC / Thrift legacy
Zipkinسازگاری با instrumentation قدیمی
Kafkaingest از صف
No-opفقط query/UI بدون pipeline ورودی

Processors و قابلیت‌های pipeline

  • Batch — کارایی نوشتن
  • Memory Limiter — back-pressure زیر فشار
  • Attributes / Filter — غنی‌سازی، redact دادهٔ حساس، کاهش volume (Filter می‌تواند trace را بشکند — با احتیاط)
  • Tail Sampling — تصمیم بعد از دیدن کل trace (مثلاً نگه داشتن فقط errorها)

OTel Collector جلوتر از Jaeger؟

اجباری نیست — خود Jaeger همان نقش collector را دارد. اگر قبلاً OTel Collector برای metrics/logs دارید، می‌تواند sidecar، DaemonSet یا remote cluster جلوی Jaeger باشد برای enrichment (نام Pod، namespace) یا sharding / tail sampling متمرکز.


Storage backends

Backendوضعیت معمولنکته
Elasticsearch 7/8 / OpenSearchرایج در بسیاری از تیم‌هاجستجوی غنی؛ هزینه و index
Cassandra 4.0+مقیاس write بالاعملیات کلاستر سنگین‌تر
ClickHouseاز v2.18 بومی (alpha)columnar، فشرده‌سازی عالی، analytics
Badgerembeddedتک‌نود، حجم متوسط
In-memoryتستبدون دوام
Remote Storage APIافزونهbackendهای certified

چرا ClickHouse مهم شد؟

حجم span نیمه‌ساخت‌یافته بالاست؛ نیاز به جستجو روی service، operation، tag، duration و trace ID دارید. گزارش‌های جامعه (از جمله CNCF blog و پست Introducing Native ClickHouse Support):

  • ingestion بالای ۵۰k spans/sec در بنچمارک تک‌نود
  • فشرده‌سازی حدود ۸.۶× روی جدول spans
  • بازیابی trace حدود ~۱۰۰ ms؛ بسیاری از searchها زیر ۵۰ ms

اسکیما برای مدل OTel در v2 بازطراحی شده: جدول spans با ستون‌های Nested، مرتب‌سازی برای search، Bloom filter روی trace_id، و materialized view برای بهینه‌سازی FindTraceIDs.


Sampling: کنترل هزینه و سربار

بدون sampling، هر درخواست = هزینهٔ storage و CPU روی مسیر hot.

نوعکی تصمیم می‌گیرد؟کاربرد
Head-based (static)ابتدای trace، درصد ثابتساده و قابل پیش‌بینی
Head-based (adaptive / remote)سرویس مرکزی احتمال را تنظیم می‌کندتعادل coverage و هزینه
Tail-basedبعد از کامل شدن traceنگه داشتن error / slow traces

Remote Sampling از طریق extension در Jaeger (و سازگاری با OTel Collector) سرو می‌شود. جزئیات در Sampling docs.


UI، Dependency Graph و SPM

Jaeger UI (:16686)

  • جستجو بر اساس service، operation، tags، مدت، بازهٔ زمانی
  • waterfall / timeline برای ده‌ها هزار span (بهبودهای v1.0+؛ آزمایش با ~۸۰٬۰۰۰ span گزارش شده)
  • contextual logs روی span

دو نوع گراف وابستگی

نوعمعنی
System Architectureوابستگی یک‌گام (A–B، B–C)؛ مثل دید mesh — لزوماً زنجیرهٔ کامل A–B–C در یک trace نیست
Deep Dependency (Transitive)با focal service؛ زنجیرهٔ تراگذاری A→B→C؛ granularity سرویس یا endpoint

System Architecture می‌تواند از memory ساخته شود یا با jobهای Spark/Flink روی storage توزیع‌شده.

Service Performance Monitoring (SPM)

از spanها metricهای تجمیعی (latency، error rate، throughput) می‌سازد و به‌صورت time series نشان می‌دهد — پلی بین tracing و «مانیتورینگ عملکرد سرویس» بدون اینکه جایگزین Prometheus کامل شود. اجزای backend معمولاً Prometheus metrics و log ساخت‌یافته (zap) هم expose می‌کنند.


سازگاری با Zipkin

اگر instrumentation قدیمی Zipkin دارید، لازم نیست همه را یک‌شبه عوض کنید. Jaeger spanهای Zipkin (Thrift، JSON v1/v2، Protobuf روی HTTP، پورت رایج :9411) را می‌پذیرد. مسیر پیشنهادی بلندمدت: مهاجرت به OpenTelemetry و OTLP.


شروع سریع

all-in-one با Docker

طبق Getting Started (نسخه را با آخرین release عوض کنید):

docker run --rm --name jaeger \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  -p 5778:5778 \
  -p 9411:9411 \
  cr.jaegertracing.io/jaegertracing/jaeger:2.20.0
  • UI: http://localhost:16686
  • OTLP gRPC: 4317 · OTLP HTTP: 4318
  • Zipkin: 9411 · Remote sampling: 5778

با config سفارشی:

docker run --rm --name jaeger \
  -p 16686:16686 -p 4317:4317 -p 4318:4318 \
  -v /path/to/config.yaml:/jaeger/config.yaml \
  cr.jaegertracing.io/jaegertracing/jaeger:2.20.0 \
  --config /jaeger/config.yaml

HotROD — دموی رسمی

HotROD (Rides on Demand) چند microservice دارد و برای یادگیری latency، concurrency، baggage و instrumentation OTel عالی است:

export JAEGER_VERSION=2.20.0   # آخرین نسخهٔ پایدار
git clone https://github.com/jaegertracing/jaeger.git jaeger
cd jaeger/examples/hotrod
docker compose up

App: http://localhost:8080 · Jaeger UI معمولاً کنار همان compose بالا می‌آید.

ارسال span با OTLP (مفهومی)

# مثال مفهومی — endpoint OTLP HTTP به all-in-one
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
export OTEL_SERVICE_NAME=checkout-api
# سپس اپ را با OpenTelemetry SDK / auto-instrumentation اجرا کنید

در Kubernetes معمولاً:

  1. Operator یا Helm chart Jaeger
  2. Instrumentation با OTel Operator / sidecars / SDK
  3. Service mesh (Istio، Linkerd) برای spanهای شبکه بدون تغییر همهٔ کد

مقایسه: Jaeger در برابر گزینه‌های رایج

معیارJaegerZipkinGrafana TempoAPM تجاری
مدلtracing backend + UI غنیسبک‌تر، legacy رایجobject store، Grafana-centricکامل + قفل
OTLP / OTelمرکز v2محدودترقویوابسته
جستجوی مستقلقوی (با ES/CH)متوسطبیشتر با TraceQL/Grafanaقوی
هزینه در مقیاسوابسته به storageکمتر ویژگیاغلب ارزان‌تر در حجمگران
CNCFGraduated
SPM / dependencyبلهمحدوداز طریق Grafanaبله

انتخاب سریع:

  • می‌خواهید UI و جستجوی standalone قوی + CNCF → Jaeger
  • قبلاً همه چیز داخل Grafana stack و object storage ارزان → Tempo را هم ارزیابی کنید
  • فقط migration کوتاه از Zipkin → Jaeger به‌عنوان drop-in backend خوب است

عملیات روزمره

کاراقدام
سلامت backendmetrics Prometheus روی اجزا؛ health extension
داده‌ای در UI نیستsampling، endpoint OTLP، clock skew، retention storage
فشار writeKafka buffer، scale collector، batch processor
PII در spanAttributes processor برای redact قبل از storage
حجم بالاadaptive / tail sampling؛ retention و ILM روی ES یا TTL روی ClickHouse
امن‌سازی UIجدا کردن query از collector؛ auth در Ingress / mesh

برای شبکه و observability مبتنی بر eBPF کنار tracing: Cilium. برای runtime security: Falco.


یکپارچگی با استک P30Light

لایهمقالهٔ مرتبط
Service meshIstio · Linkerd
Data planeEnvoy · Contour
LogsFluentd
GitOps استقرارFlux · Helm
رویدادCloudEvents
App runtimeDapr

الگوی رایج production:

Apps / Mesh ──OTLP──► OTel Collector (enrich) ──► Jaeger collector
                                              └──► (اختیاری) metrics/logs backends
Jaeger storage ◄── collector / Kafka+ingester
UI / SPM ◄── query

خلاصه

موضوعجمع‌بندی
چیستپلتفرم distributed tracing open source (CNCF Graduated)
v2مبتنی بر OpenTelemetry Collector؛ نقش‌های collector/query/…
ورود دادهOTLP اول؛ Zipkin و Jaeger legacy پشتیبانی می‌شوند
StorageES/OpenSearch، Cassandra، Badger، ClickHouse (native از 2.18)
UIجستجوی trace، waterfall، dependency، SPM
Scaleبدون SPOF؛ Kafka برای بافر؛ میلیاردها span/روز در مقیاس Uber
InstrumentOpenTelemetry SDK توصیهٔ رسمی

قدم بعدی

  1. all-in-one را با Docker بالا بیاورید و UI را روی :16686 باز کنید.
  2. HotROD را با docker compose اجرا کنید و یک latency cascade را در waterfall ببینید.
  3. یک سرویس واقعی را با OTel SDK به 4317/4318 وصل کنید.
  4. برای staging، collector/query جدا + Elasticsearch یا ClickHouse انتخاب کنید.
  5. sampling (adaptive یا tail) را قبل از production کامل روشن کنید.
  6. با mesh یا Fluentd، سه ستون metrics / logs / traces را هم‌تراز کنید.

منابع

منتشر شده در P30Light — بخش زیرساخت و سرور

لینک گزارش با موفقیت کپی گردید!