首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >全链路监控:打通前后端链路的最后一公里

全链路监控:打通前后端链路的最后一公里

作者头像
SRE运维手记
发布2024-11-25 17:38:45
发布2024-11-25 17:38:45
51100
代码可运行
举报
文章被收录于专栏:SRE运维手记SRE运维手记
运行总次数:0
代码可运行

全链路监控(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的代码进行小改动。

  • 修改后的Skywalking Nginx Agent,下载地址
代码语言:javascript
代码运行次数:0
运行
复制
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编译安装秘笈:实用模块与自动化部署的完美结合》的基础上进行。

  • 将skywalking-nginx-lua-0.6.0.tar.gz解压至路径/app/nginx/module
代码语言:javascript
代码运行次数:0
运行
复制
tar zxvf skywalking-nginx-lua-0.6.0.tar.gz -C /app/nginx/module
  • 安装lua-cjson,Skywalking Nginx Agent依赖它,否则访问站点会报错
代码语言:javascript
代码运行次数:0
运行
复制
# 下载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
  • lua-cjson安装成功后,就可以通过编译增加skywalking-nginx-lua-0.6.0模块了
代码语言:javascript
代码运行次数:0
运行
复制
# 编译
./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
  • 模块添加后,还需要在nginx.conf的http上下文中引用Skywalking Nginx Agent
代码语言:javascript
代码运行次数:0
运行
复制
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")
}
  • 接着在需要监控链路信息的vhost进行埋点,并将Nginx的RequestID传给前后端
代码语言:javascript
代码运行次数:0
运行
复制
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()
            }    
    }
    ... ...
}
  • 最后就是配置reload了,由于reload时不检查lua的语法,所以建议在配置验证后再上生产
代码语言:javascript
代码运行次数:0
运行
复制
systemctl reload nginx

05、结 语

通过上述配置和前后端代码实现TraceID赋值后,我们就可以统一前端、网关及后端的TraceId,打通整个请求链路了,在问题排查和性能分析上大大提效,本期就分享到这里,谢谢!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-11-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SRE运维手记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档