写点什么

APISIX 可观测性最佳实践

作者:观测云
  • 2024-02-20
    上海
  • 本文字数:3756 字

    阅读完需:约 12 分钟

APISIX 可观测性最佳实践

APISIX 介绍

Apache APISIX 是一个动态、实时、高性能的云原生 API 网关。它构建于 NGINX + ngx_lua 的技术基础之上,充分利用了 LuaJIT 所提供的强大性能。


APISIX 主要分为两个部分:


  • APISIX 核心:包括 Lua 插件、多语言插件运行时(Plugin Runner)、Wasm 插件运行时等;

  • 功能丰富的各种内置插件:包括可观测性、安全、流量控制等。


APISIX 在其核心中,提供了路由匹配、负载均衡、服务发现、API 管理等重要功能,以及配置管理等基础性模块。除此之外,APISIX 插件运行时也包含其中,提供原生 Lua 插件的运行框架和多语言插件的运行框架,以及实验性的 Wasm 插件运行时等。APISIX 多语言插件运行时提供多种开发语言的支持,比如 Golang、Java、Python、JS 等。


APISIX 目前也内置了各类插件,覆盖了 API 网关的各种领域,如认证鉴权、安全、可观测性、流量管理、多协议接入等。本文中的可观测性就是基于 APISIX 的插件来实现数据上报。

案例介绍

本 demo 案例采用了 Ruoyi 系统 + APISIX 的最佳实践,采用了 Opentelemetry + DDtrace 多链路协议的方式,以下是具体版本信息:


DataKit Agent:v1.22.1


DataKit Operator:v1.2.1


APISIX:v3.2 (LTS)


  • Opentelemetry-plugin


Ruoyi:v3.6.3


  • Vue 前端 SDK:Opentelemetry

  • Java 后端 SDK:DDtrace

如何接入

APISIX 的可观测性有多种插件和接入方式,我们以下面的几种插件来举例说明:



Tracing

1、RUM 接入改造

前端 npm sdk 版本 保持最新版本即可


RUM 接入时需要修改 traceType 修改为 w3c_traceparent


traceType: 'w3c_traceparent'
复制代码


开启效果:


开启后,可实现前端 w3c 协议头上报 , 在请求头中可以查看到 w3c 的协议头 Traceparent 请求头至后端,方便客户排障时获取关联的 trace_id 。



2、Opentelemetry 插件开启

官方参考文档: https://apisix.apache.org/docs/apisix/plugins/opentelemetry/


APISIX Dashboard opentelemetry 的配置


{     "additional_attributes": [         "resp_body",         "balancer_ip",         "route_name"     ],    "disable": false,     "sampler": {         "name": "always_on"     } }
复制代码


在插件市场配置如下所示:



在 Apisix config.yaml 关于 otel 的配置


plugins: - opentelemetryplugin_attr:   opentelemetry:     resource:       service.name: APISIX       tenant.id: business_id     collector:       address: 127.0.0.1:9529/otel       request_timeout: 3       #request_headers:       # foo: bar     batch_span_processor:       drop_on_queue_full: false       max_queue_size: 6       batch_timeout: 2       inactive_timeout: 1       max_export_batch_size: 2
复制代码


其中 127.0.0.1:9529/otel 是 datakit 的上报 trace 的地址,datakit 完整的上报地址是 127.0.0.1:9529/otel/v1/trace


但是 apisix 上报 trace 的路径是 /v1/traces ,两者路径不一致,需要在 APISIX 上对 datakit 的上报路径做个转发。

3、Datakit 开启 Opentelemetry 采集

1)参考 https://docs.guance.com/datakit/opentelemetry/ ,开启 otel 采集器采集;2)修改 DataKit 默认上报的 Opentelemetry 路径,trace_api 修改为 /otel/v1/traces ,若 key 不存在,添加即可。


  • apisix 默认上报 路径 /v1/traces

  • DataKit 默认接收 路径 /otel/v1/trace


[[inputs.opentelemetry]]  ## During creating 'trace', 'span' and 'resource', many labels will be added, and these labels will eventually appear in all 'spans'  ## When you don't want too many labels to cause unnecessary traffic loss on the network, you can choose to ignore these labels  ## with setting up an regular expression list.  ## Note: ignore_attribute_keys will be effected on both trace and metrics if setted up.  # ignore_attribute_keys = ["os_*", "process_*"]  ## The acceptable http_status_ok values will be 200 or 202.       [inputs.opentelemetry.http]   enable = true   http_status_ok = 200   trace_api = "/otel/v1/traces"
复制代码


配置好 opentelemetry.conf 之后,采用 systemctl restart datakit 重启 datakit ,配置生效。


注意:http 协议的路由是不可配置的,请求路径(Trace/Metric)分别为 /otel/v1/trace/otel/v1/metric


上报完成之后,可以在观测云上看的采集 APISIX 的 trace 信息。


最终效果:




Loggers

1、日志改造

1.1、日志文件输出方式

file-loggger 插件


实际配置效果


{     "disable": false,     "include_resp_body": true,     "include_resp_body_expr": false,     "path": "/usr/local/apisix/logs/file.log" }
复制代码


在插件市场配置如下所示:



注意:path 的路径需要是绝对路径,不能写成相对的,配置成功之后,查看日志文件是否有日志生成。

1.2、console 输出方式

修改配置文件 conf/config.yaml ,修改访问日志格式 access_logger_format 。


nginx_config:  http:    access_log_format: '{"remote_addr": "$remote_addr", "remote_user": "$remote_user", "time_local": "$time_local", "http_host": "$http_host", "request": "$request", "status": "$status", "body_bytes_sent": "$body_bytes_sent", "request_time": "$request_time", "http_referer": "$http_referer", "http_user_agent": "$http_user_agent", "upstream_addr": "$upstream_addr", "upstream_status": "$upstream_status", "upstream_response_time": "$upstream_response_time", "upstream_url": "$upstream_scheme://$upstream_host$upstream_uri","x-gc-trace-id": "$http_x_gc_trace_id","x-gc-span-id": "$http_x_gc_span_id","traceparent": "$http_traceparent"}'
复制代码


其中 traceparent 的值为标准 W3C 128-bit trace_id

2、日志切割

2.1、pipeline 日志切割转换

pipeline 编写参考


if vaild_json(_) { # true  origin = load_json(_)  add_key(remote_addr,origin["remote_addr"])  add_key(remote_user,origin["remote_user"])  add_key(http_host,origin["http_host"])  add_key(request,origin["request"])  add_key(http_referer,origin["http_referer"])  add_key(body_bytes_sent,origin["body_bytes_sent"])  add_key(upstream_url,origin["upstream_url"])

add_key(trace_id,origin["traceparent"]) grok(trace_id, "%{DATA}-%{DATA:trace_id}-%{DATA}")
}
复制代码


测试效果如下:



Metric

1、APISIX 开启 Promethues 插件

官方参考链接:https://apisix.apache.org/docs/apisix/plugins/prometheus/



2、Datakit 开启 Promethues 采集

在观测云平台中,点击「集成」中,选择「APISIX」可以通过 promethues 的方式采集 APISIX 数据。



日志和 trace 数据关联

apisix 导出的日志格式如下:


{"client_ip":"127.0.0.1","server": {"hostname":"localhost.localdomain","version":"2.14.1"},"apisix_latency":0,"upstream":"127. 0.0.1:9529","upstream_latency":1,"request": {"url":"http:\/\/127.0.0.1:80\/otel\/v1\/traces","size":836,"uri":"\/otel\/v1\/traces","que rystring":{},"headers":{"content-type":"application\/x-protobuf","user-agent":"lua-resty- http\/0.16.1 (Lua) ngx_lua\/10021","content-length":"672","traceparent":"00-749cc2e62e47bcf01fb76932c74ec1fe-d0a6101332bca613-01","host":"127.0.0.1"},"method":"POST"},"latency":0.99992752075195,"start_time":1685688047 197,"service_id":"","route_id":"462899766133524220","response": {"size":493,"status":200,"headers":{"access-control-allow-headers":"Content-Type, Content- Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X- Requested-With, X-Token, X-Datakit-UUID, X-RP, X-Precision, X-Lua","access-control-allow- credentials":"true","server":"APISIX\/2.14.1","content-length":"0","access-control-allow- origin":"*","x-datakit":"1.5.7\/2023-03-20 11:50:32","connection":"close","access-control- allow-methods":"POST, OPTIONS, GET, PUT","date":"Fri, 02 Jun 2023 06:40:47 GMT"}}}
复制代码


通过以上日志,我们可以看到 traceparent 信息:


"traceparent":"00-749cc2e62e47bcf01fb76932c74ec1fe-d0a6101332bca613-01"


这是 opentelemetry 所产生的 trace 数据,其中749cc2e62e47bcf01fb76932c74ec1fe 才是对应的 trace_id 信息,这个时候需要通过观测云的 Pipelines 做下切割,切割的脚本可以参考如下:


json(_, client_ip, client_ip) json(_, upstream, upstream) json(_, request.url, url) json(_, response.status, http_status) json(_, route_id, route_id) json(_, request.headers.traceparent, trace_id) grok(_, "%{DATA}traceparent\":\"%{DATA}-%{DATA:trace_id}-%{DATA}\"") 
复制代码


trace_id 就被切割出来了,00-749cc2e62e47bcf01fb76932c74ec1fe-d0a6101332bca613-01 切割成749cc2e62e47bcf01fb76932c74ec1fe


因为 tracing 的 id 和日志的 id 一致,所以可以通过观测云关联起来,效果如下:



用户头像

观测云

关注

还未添加个人签名 2021-02-08 加入

云时代的系统可观测平台

评论

发布
暂无评论
APISIX 可观测性最佳实践_APISIX_观测云_InfoQ写作社区