分布式集群环境下调用链路追踪(4)Node.js 下 Trace 介绍以及实践
- UID
- 1066743
|
分布式集群环境下调用链路追踪(4)Node.js 下 Trace 介绍以及实践
Node.js 下 Trace 介绍以及实践Node.js 追踪是通过与 Zipkin 集成来实现的,具体是通过 Express 与 Zipkin 集成来完成,两者的集成非常简单,并且入侵性也小。
集成介绍- Express Server:Express Server 与 Zipkin 的集成,即 Server 接收到请求时把自身的调用信息发送到 Zipkin。
- Rest Client:服务 A 调用服务 B 时,服务 A 把调用链信息发送到 Zipkin。
- Tracer:根据 context 把记录的 Span 信息通过 Recorder 发送到 Zipkin。
- Recorder:发送信息到 Zipkin,支持两种方式,一种是直接发送到 Zipkin Server,还有一种是控制台输出,控制台输出的方式可以用来调试,本 demo 中我们选择第一种方式。
创建 demo-front 工程限于篇幅问题,将涉及 Node.js 的 demo-frontend、demo-backend 都放在 工程中。
- 新建一个基于 Node.js 的项目,项目名称为:demo-front。
- 项目 package.json 配置如下: 清单 6. package.json 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| {
"name": "demo-front",
"version": "0.0.1",
"description": "Example project that shows how to use zipkin with javascript",
"repository": "https://github.com/openzipkin/zipkin-js",
"scripts": {
"lint": "eslint .",
"start": "node servers.js",
"browserify": "browserify browser.js -o bundle.js"
},
"dependencies": {
"browser-process-hrtime": "^0.1.2",
"express": "^4.14.0",
"rest": "^1.3.2",
"zipkin": "^0.11.1",
"zipkin-context-cls": "^0.11.0",
"zipkin-instrumentation-cujojs-rest": "^0.11.1",
"zipkin-instrumentation-express": "^0.11.1",
"zipkin-instrumentation-fetch": "^0.11.1",
"zipkin-transport-http": "^0.11.1"
},
"devDependencies": {
"browserify": "^14.1.0",
"eslint": "^3.4.0",
"eslint-config-airbnb": "^14.1.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-react": "^6.2.0"
}
}
|
- 创建 frontend.js,后续将使用 frontend.js 作为最前端调用 demo-web,完成 Node.js 端调用 Java Web 模块的 Trace 模拟,如清单 7 所示,完整代码参照项目:frontend.js。 清单 7. frontend.js 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| app.get('/redis', (req, res) => {
var url_parts = url.parse(req.url, true);
var query = url_parts.query;
res.header('X-B3-TraceId', tracer.id.traceId);
res.header('X-B3-SpanId', tracer.id.spanId);
tracer.local('docs-front', () =>
zipkinRest(`http://localhost:8080/docs/web/callredis?msg=${query.msg}`)
.then(response => res.send(response.entity))
.catch(err => console.error('Error', err.stack))
);
console.log(`tracerId : ${tracer.id.traceId}, spanId : ${tracer.id.spanId}`);
});
app.get('/kafka', (req, res) => {
var url_parts = url.parse(req.url, true);
var query = url_parts.query;
res.header('X-B3-TraceId', tracer.id.traceId);
res.header('X-B3-SpanId', tracer.id.spanId);
tracer.local('docs-front', () =>
zipkinRest(`http://localhost:8080/docs/web/callkafka?msg=${query.msg}`)
.then(response => res.send(response.entity))
.catch(err => console.error('Error', err.stack))
);
console.log(`tracerId : ${tracer.id.traceId}, spanId :
${tracer.id.spanId}`);
});
|
- 创建 backend.js,如清单 8 所示。后续将使用 backend.js 作为最后端,完成 Node.js 端调用 Java 模块,然后 Java 模块调用 Node.js 模块的一套完整的 Trace 模拟。 清单 8. backend.js 代码
1
2
3
4
5
6
7
8
| app.get('/api', (req, res) => {
var url_parts = url.parse(req.url, true);
var query = url_parts.query;
console.log(`docs-backend msg : ${query.msg}`);
console.log(`docs-backend tracerId : ${tracer.id.traceId}, spanId :
${tracer.id.spanId}`);
res.send(new Date().toString())
});
|
|
|
|
|
|
|