乐趣区

关于apisix: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 的可观测性有多种插件和接入形式,咱们以上面的几种插件来举例说明:

品种 接入形式(插件)
Tracers opentelemetry 插件,可用于依据 OpenTelemetry specification 协定标准上报 Tracing 数据。(该插件目前仅反对 http 申请上报)
Loggers 1、file-logger 插件,可用于将日志数据存储到指定地位。2、console 输入形式,可用于批改 APISIX 的 access_log 文件格式
Metrics prometheus 插件,以规定的格局上报指标到 Prometheus 中。

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:
 - opentelemetry
plugin_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 统一,所以能够通过观测云关联起来,成果如下:

退出移动版