隨着互聯網業務的不斷增長,單一服務越來越難以支撐整個業務的需求,因此出現了分布式系統架構。在分布式架構中,一次業務請求可能會涉及多個服務之間的調用,此時需要一種工具來協調和追蹤整個請求的流轉情況,即分布式鏈路追蹤。
一、分布式鏈路追蹤監控插件
分布式鏈路追蹤監控插件是實現分布式鏈路追蹤的一種方式。通過將監控插件添加到業務系統中,在請求的不同階段打標記並上報到追蹤系統中,就可以了解整個請求的調用鏈路,並通過可視化界面展示出來。
Java 示例:
public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { Tracer tracer = GlobalTracer.get(); Span span = tracer.buildSpan("my-filter").start(); Tags.COMPONENT.set(span, "my-servlet"); try (Scope ignored = tracer.activateSpan(span)) { chain.doFilter(request, response); } finally { span.finish(); } } @Override public void destroy() { } }
Python 示例:
@app.route('/hello') def hello(): with tracer.start_active_span('hello') as scope: sid = uuid.uuid1().hex scope.span.set_tag('sid', sid) result = requests.get('http://localhost:8080/world') return 'hello, world!'
二、分布式統計和過濾的鏈路追蹤
分布式統計和過濾的鏈路追蹤除了具備監控插件的功能外,還可以對鏈路數據進行統計和過濾。通過在請求頭和響應頭中添加特定的字段,在追蹤系統中可以對鏈路的運行時間、錯誤次數等信息進行統計,並設置告警策略。同時,也可以根據需求對鏈路數據進行篩選和聚合,以便更好地了解業務請求的情況。
Go 示例:
func Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { url, _ := url.Parse(r.URL.String()) span, ctx := opentracing.StartSpanFromContext(r.Context(), "http") opentracing.Tag{Key: "http.method", Value: r.Method}.Set(span) opentracing.Tag{Key: "http.url", Value: url.Path}.Set(span) opentracing.Tag{Key: "http.query", Value: url.RawQuery}.Set(span) opentracing.Tag{Key: "http.host", Value: r.Host}.Set(span) opentracing.Tag{Key: "http.protocol", Value: r.Proto}.Set(span) defer span.Finish() w.Header().Add("Span-Id", span.Context().(SpanContext).TraceID().String()) ctx = opentracing.ContextWithSpan(r.Context(), span) r = r.WithContext(ctx) next.ServeHTTP(w, r) }) }
三、分布式鏈路追蹤傳遞上下文
在分布式架構中,一次請求可能會經過多個服務,需要將調用鏈路上的上下文信息傳遞下去,以方便追蹤整個請求的流轉情況。標準的傳遞方式是將上下文信息放在 HTTP 頭中進行傳遞。具體實現方式可以使用各個編程語言提供的追蹤庫。
PHP 示例:
function curl($url) { $parentSpan = $tracer->getActiveSpan(); $opts = [ 'http' => [ 'method' => 'GET', 'header' => [ 'X-B3-TraceId: ' . $parentSpan->getContext()->getTraceId(), 'X-B3-SpanId: ' . $parentSpan->getContext()->getSpanId(), 'X-B3-ParentSpanId: ' . $parentSpan->getContext()->getParentId() ] ] ]; $context = stream_context_create($opts); $response = file_get_contents($url, false, $context); return json_decode($response, true); }
四、分布式鏈路追蹤框架
分布式鏈路追蹤框架是對分布式鏈路追蹤進行封裝的工具,旨在提供便捷的使用體驗。一般來說,分布式鏈路追蹤框架需要具備以下特性:
- 支持多種追蹤後端,比如 Zipkin、Jaeger;
- 提供豐富的 API,方便集成;
- 支持跨語言的追蹤鏈路;
- 支持鏈路信息靈活採樣,減輕追蹤系統壓力。
Node.js 示例:
const Tracer = require('jaeger-client').Tracer; const opentracing = require('opentracing'); const tracer = new Tracer({ serviceName: 'hello-world', sampler: { type: 'const', param: 1, }, reporter: { logSpans: true, agentHost: 'localhost', agentPort: 6832, } }); opentracing.initGlobalTracer(tracer);
五、分布式鏈路追蹤有哪些
目前常用的分布式鏈路追蹤工具主要包括 Zipkin、Jaeger、SkyWalking 等。
- Zipkin:國內外比較常用的分布式鏈路追蹤工具,使用 Google 的 Dapper 作為參考,初版於 2012 年開發出來,已經發展得非常成熟;
- Jaeger:Uber 開源的分布式鏈路追蹤工具,支持多語言,特別是對 Go 語言的支持非常好;
- SkyWalking:Apache 基金會孵化的 APM 工具,早期使用的是基於字節碼增強的方式實現,後來也支持了插件的方式;
Zipkin 示例:
docker run -d -p 9411:9411 openzipkin/zipkin
Jaeger 示例:
docker run -d -p 5775:5775/udp -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 -p 16686:16686 -p 14268:14268 jaegertracing/all-in-one:latest
SkyWalking 示例:
docker run -d -p 8080:8080 apache/skywalking-oap-server
六、分布式鏈路追蹤技術
分布式鏈路追蹤涉及到的技術主要包括分布式系統和追蹤系統兩個方面:
- 分布式系統:在分布式系統中,面臨著多個服務之間互相調用的挑戰。為了解決這個問題,需要使用一些分布式技術,比如分布式一致性算法、分布式事務等;
- 追蹤系統:對於追蹤系統來說,需要對請求鏈路進行跟蹤和統計。這就需要用到開發語言的追蹤庫以及一些可視化的追蹤工具。
Java 示例:
@Bean public Tracer jaegerTracer() { return new io.jaegertracing.Configuration(jaegerServiceName, samplerConfig, reporterConfig) .getTracer(); }
七、分布式鏈路追蹤組件
除了常見的追蹤工具外,還有一些組件可以集成在應用中,便於進行分布式鏈路追蹤。
- OpenTracing:CNCF 組織推出的跟蹤標準,提供統一的 API 以及多種編程語言的實現方式;
- Spring Cloud Sleuth:Spring Cloud 基於 OpenTracing 平台的分布式鏈路追蹤框架,提供對 Zipkin 的集成;
- Dapper:Google 開源的跟蹤系統,後來成為 Zipkin 的靈感來源。
OpenTracing 示例:
Tracer tracer = Configuration.fromEnv().getTracer(); Span span = tracer.buildSpan("user-query").start(); span.setTag("user-id", "12345"); try { ... } catch (Exception e) { span.setTag("error", true); } finally { span.finish(); }
八、分布式鏈路追蹤系統
分布式鏈路追蹤系統是對分布式鏈路追蹤進行統一管理的工具,一般包括追蹤器、存儲器、查詢器等模塊。通過將分布式鏈路追蹤數據集中存儲,方便進行查看和分析。
Zipkin 示例:
docker run -d -p 9411:9411 openzipkin/zipkin
九、分布式鏈路追蹤工具
分布式鏈路追蹤工具是對分布式鏈路追蹤進行可視化展示和分析的工具,可以使用界面來查看鏈路的調用情況,方便問題排查和性能優化。
Zipkin 示例:
docker run -d -p 9411:9411 openzipkin/zipkin
Jaeger 示例:
docker run -d -p 5775:5775/udp -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 -p 16686:16686 -p 14268:14268 jaegertracing/all-in-one:latest
十、分布式鏈路追蹤實現選取
在選取分布式鏈路追蹤實現時,需要根據實際需求來進行選擇。一般需要考慮以下幾個方面:
- 語言支持:判斷追蹤框架是否支持應用所使用的語言;
- 性能:對追蹤框架性能進行評估,看是否對業務系統帶來過多負擔;
- 社區活躍度:優先選擇社區活躍、開發維護頻繁的追蹤框架;
- 集成便捷性:判斷追蹤框架是否提供了豐富的
原創文章,作者:WLJM,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/137718.html