全链路监控(End-to-End Monitoring)是一种应用性能管理(APM)的方法,旨在对应用程序的整个运行链路进行监控和管理,从用户请求发起到最终响应返回的完整流程。我们关注应用程序在各个层面的性能表现和数据流动,包括前端用户界面、服务端逻辑、数据库、网络通信等。通过全链路监控,可以掌握应用程序的各个环节的性能指标、调用关系和异常情况,以便进行及时的故障诊断、性能优化和资源规划。
01、背景
本次分享的是一个基于JAVA的微服务应用场景。后端使用SkyWalking进行链路监控,前端使用Sentry进行性能和异常监控。然而,在排查用户侧问题和优化站点性能时,前后端请求的关联性较差。因此,我们考虑使用Nginx的RequestID作为链路TrackID,将前后端链路打通,从而实现更高效的监控和问题排查。
02、方案拓扑
如上图,用户通过前端发起请求,经过Nginx,再经微服务网关路由到微服务,微服务之间有相互调用。前端的信息和异常会上报给Sentry,后端的链路信息会上报给Skywalking。我们要做的就是统一TraceId,将整个链路打通。
03、模块改动说明
为了统一Sentry、Nginx和Skywalking的TraceId,我们考虑使用RequestID给TraceId赋值,因此,需要对Skywalking Nginx Agent的代码进行小改动。
wget https://github.com/yilingyi/skywalking-nginx-lua-0.6.0/releases/download/0.6.0/skywalking-nginx-lua-0.6.0.tar.gz
1. 修改tracing_context.lua,给链路追踪构造函数传递RequestID
2. 修改tracing_context.lua,将RequestID赋值给TraceId
04、操作步骤
Skywalking Nginx Agent模块的添加是基于之前分享的《Nginx编译安装秘笈:实用模块与自动化部署的完美结合》的基础上进行。
tar zxvf skywalking-nginx-lua-0.6.0.tar.gz -C /app/nginx/module
# 下载lua-cjson
wget https://github.com/yilingyi/lua-cjson/releases/download/2.1.0.8/lua-cjson-2.1.0.8.tar.gz
# 解压
tar zxvf lua-cjson-2.1.0.8.tar.gz
# 进入目录
cd lua-cjson-2.1.0.8
# 编译
cc -c -O3 -Wall -pedantic -DNDEBUG -I/app/nginx/module/luajit/include/luajit-2.0 -fpic -o lua_cjson.o lua_cjson.c
# 安装
make && make install
# 编译
./configure --conf-path=/app/nginx/conf/nginx.conf \
--user=nginx \
--group=nginx \
--prefix=/app/nginx \
--with-stream \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_ssl_module \
--with-http_sub_module \
--with-http_v2_module \
--add-module=/app/nginx/module/nginx_upstream_check_module-0.4.0 \
--with-ld-opt=-Wl,-rpath,/app/nginx/module/luajit/lib \
--add-module=/app/nginx/module/headers-more-nginx-module-0.33 \
--add-module=/app/nginx/module/ngx_devel_kit-0.3.0 \
--add-module=/app/nginx/module/lua-nginx-module-0.10.10 \
--add-module=/app/nginx/module/set-misc-nginx-module-0.31 \
--add-module=/app/nginx/module/skywalking-nginx-lua-0.6.0
# 安装
make && make install
http {
include mime.types;
default_type application/octet-stream;
... ...
# skywalking-nginx-lua模块的路径
lua_package_path "/app/nginx/module/skywalking-nginx-lua-0.6.0/lib/?.lua;;";
# 共享字典,在高并发或大量上报数据的场景中,共享字典用于缓存链路信息时,如果分配的内存大小不足,可能会导致部分链路信息被丢弃
lua_shared_dict tracing_buffer 1024m;
init_worker_by_lua_block {
local metadata_buffer = ngx.shared.tracing_buffer
# 定义上报skywalking的服务名称
metadata_buffer:set('serviceName', 'yilingyi-nginx')
# 定义上报skywalking的服务名称下的实例名,如果有多nginx实例,可以用这个配置进行区分
metadata_buffer:set('serviceInstanceName', 'yilingyi-nginx-1')
metadata_buffer:set('includeHostInEntrySpan', false)
require("skywalking.util").set_randomseed()
# skywalking oap服务的接口地址
require("skywalking.client"):startBackendTimer("http://172.101.0.6:12800")
skywalking_tracer = require("skywalking.tracer")
}
server {
listen 80;
... ...
underscores_in_headers on;
# 返回给前端,前端在拦截处增加extra附加信息traceid
add_header x-request-id $request_id;
location /api {
# 请求开始时的埋点
rewrite_by_lua_block {
skywalking_tracer:start("upstream service")
}
proxy_pass http://yilingyi_backend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 传递给后端,后端在获取后给traceid赋值
proxy_set_header x-request-id $request_id;
# 请求结束时的埋点
body_filter_by_lua_block {
if ngx.arg[2] then
skywalking_tracer:finish()
end
}
# 日志记录阶段的埋点
log_by_lua_block {
skywalking_tracer:prepareForReport()
}
}
... ...
}
systemctl reload nginx
05、结 语
通过上述配置和前后端代码实现TraceID赋值后,我们就可以统一前端、网关及后端的TraceId,打通整个请求链路了,在问题排查和性能分析上大大提效,本期就分享到这里,谢谢!