一、依賴任務(wù)
1.1 k8s運(yùn)行任務(wù)
# https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/
# https://github.com/jaegertracing/jaeger-kubernetes
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: jaeger-spark-dependencies
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
- name: dependencies
image: jaegertracing/spark-dependencies
env:
- name: STORAGE
value: "elasticsearch"
- name: ES_NODES
value: "jaeger-elasticsearch:9200"
- name: ES_USERNAME
value: "elastic"
- name: ES_PASSWORD
value: "changeme"
restartPolicy: OnFailure
1.2 查看任務(wù)狀態(tài)
kubectl get cj
kubectl describe cj jaeger-spark-dependencies
1.3 依賴關(guān)系結(jié)果
[
{
"parent": "frontend",
"callCount": 92,
"source": "jaeger",
"child": "frontend"
},
{
"parent": "frontend",
"callCount": 4,
"source": "jaeger",
"child": "driver"
},
{
"parent": "frontend",
"callCount": 40,
"source": "jaeger",
"child": "route"
},
{
"parent": "frontend",
"callCount": 4,
"source": "jaeger",
"child": "customer"
},
{
"parent": "mysql",
"callCount": 4,
"source": "jaeger",
"child": "mysql"
},
{
"parent": "boot-service",
"callCount": 1030,
"source": "jaeger",
"child": "boot-service"
},
{
"parent": "customer",
"callCount": 4,
"source": "jaeger",
"child": "mysql"
},
{
"parent": "driver",
"callCount": 54,
"source": "jaeger",
"child": "redis"
}
]
二、依賴任務(wù)實(shí)現(xiàn)
io.jaegertracing.spark.dependencies.elastic.ElasticsearchDependenciesJob
整體思路是:
1)從ES集群查詢數(shù)據(jù),獲取span列表
2)根據(jù)traceId將Span進(jìn)行分組
3)計(jì)算每個(gè)分組中所有span的依賴關(guān)系

image.png
4)聚合依賴關(guān)系,并寫入ES
三、依賴Http接口實(shí)現(xiàn)
cmd/query/app/http_handler.go:dependencies
用戶需要傳入時(shí)間范圍,然后獲取數(shù)據(jù)。
// 請(qǐng)求示例URL http://localhost:16686/api/dependencies?endTs=1574408925476&lookback=604800000
func (aH *APIHandler) dependencies(w http.ResponseWriter, r *http.Request) {
endTsMillis, err := strconv.ParseInt(r.FormValue(endTsParam), 10, 64)
if aH.handleError(w, errors.Wrapf(err, "unable to parse %s", endTimeParam), http.StatusBadRequest) {
return
}
var lookback time.Duration
if formValue := r.FormValue(lookbackParam); len(formValue) > 0 {
lookback, err = time.ParseDuration(formValue + "ms")
if aH.handleError(w, errors.Wrapf(err, "unable to parse %s", lookbackParam), http.StatusBadRequest) {
return
}
}
service := r.FormValue(serviceParam)
if lookback == 0 {
lookback = defaultDependencyLookbackDuration
}
endTs := time.Unix(0, 0).Add(time.Duration(endTsMillis) * time.Millisecond)
// 查詢指定范圍內(nèi)的依賴關(guān)系
dependencies, err := aH.queryService.GetDependencies(endTs, lookback)
if aH.handleError(w, err, http.StatusInternalServerError) {
return
}
// 如果用戶傳入服務(wù)名,根據(jù)服務(wù)名過(guò)濾依賴
filteredDependencies := aH.filterDependenciesByService(dependencies, service)
// 以parent和child為key,聚合數(shù)據(jù)
structuredRes := structuredResponse{
Data: aH.deduplicateDependencies(filteredDependencies),
}
aH.writeJSON(w, r, &structuredRes)
}
四、參考文檔
https://github.com/openzipkin/zipkin-dependencies
https://github.com/jaegertracing/spark-dependencies
https://segmentfault.com/a/1190000021063578
http://www.itdecent.cn/p/e26c5a9b5261