NGINX和NGINX Plus的OpenTracing

NGINX | 2019年6月17日

尽管有诸多优势,微服务架构也带来了新的复杂性。其中一项挑战是,在构成应用的所有微服务之间传输数据时,跟踪请求的处理过程。为此,人们提出了一种名为分布式(请求)追踪的新方法,而OpenTracing是一套规范和标准API,旨在指导分布式追踪工具的设计与实现。

在NGINX Plus Release 18(R18)中,我们将NGINX OpenTracing模块添加到了动态模块存储库中(此前,它已作为GitHub上的第三方模块提供了数年)。NGINX OpenTracing模块的一大优势是,只需对NGINX和NGINX Plus进行分布式追踪插桩,即可获取每个代理应用的追踪数据,无需逐一对应用进行插桩。

本文介绍如何为NGINX或NGINX Plus的请求启用分布式追踪(为简洁起见,下文统称为“NGINX Plus”)。本文提供两种分布式追踪服务(在OpenTracing术语中称为“追踪器”)的配置说明,即Jaeger和Zipkin。(如需查看其他追踪器的列表,请参阅OpenTracing文档。)为说明追踪器可提供的信息,本文对比了启用NGINX Plus缓存前后的请求处理情况。

追踪器包含两个基本组件:

  • 一种代理,用于从与其运行在同一主机上的应用程序中收集跟踪数据。在本例中,“应用程序”是NGINX Plus,代理以插件形式实现。
  • 一种服务器(也称为“收集器”),用于接收来自一个或多个代理的跟踪数据,并将其显示在中央UI中。可根据需要在NGINX Plus主机或其他主机上运行该服务器。

安装跟踪服务器

第一步是为所选的追踪器安装并配置服务器。本文提供了 Jaeger 和 Zipkin 的操作说明;如使用其他追踪器,请根据需要进行调整。

安装Jaeger服务器

建议使用以下方法安装Jaeger服务器。也可以通过步骤 1 中指定的URL下载Docker镜像。

  1. 转到Jaeger 下载页面,然后下载 Linux 二进制文件(撰写本文时为 jaeger-1.12.0-linux-amd64.tar)。
  2. 将二进制文件移至/usr/bin/jaeger(如有必要,请先创建该目录),然后运行该文件。
$ mkdir /usr/bin/jaeger$ mv jaeger-1.12.0-linux-amd64.tar /usr/bin/jaeger
$ cd /usr/bin/jaeger
$ tar xvzf jaeger-1.12.0-linux-amd64.tar.gz
$ sudo rm -rf jaeger-1.12.0-linux-amd64.tar.gz
$ cd jaeger-1.12.0-linux-amd64
$ ./jaeger-all-in-one
  1. 确认可在浏览器中通过 http://Jaeger-server-IP-address:16686/ 访问Jaeger UI(16686是Jaeger服务器的默认端口)。

安装Zipkin服务器

  1. 下载并运行Zipkin的Docker镜像(此处使用默认端口9411)。
$ docker run -d -p 9411:9411 openzipkin/zipkin
  1. 确认可在浏览器中通过 http://Zipkin-server-IP-address:9411/ 访问 Zipkin UI。

安装和配置追踪器插件

在NGINX Plus主机上运行以下命令,安装Jaeger或Zipkin插件。

安装Jaeger插件

  1. 安装Jaeger插件。以下wget命令适用于x86-64 Linux系统:
$ cd /usr/local/lib
$ wget https://github.com/jaegertracing/jaeger-client-cpp/releases/download/v0.4.2/libjaegertracing_plugin.linux_amd64.so -O /usr/local/lib/libjaegertracing_plugin.so
  1. 有关从源代码构建插件的说明,请参阅GitHub。
  2. 为该插件创建一个JSON格式的配置文件,将其命名为/etc/jaeger/jaeger-config.json,并写入以下内容。此处使用Jaeger服务器的默认端口6831:
{  "service_name": "nginx",
  "sampler": {
    "type": "const",
    "param": 1
  },
  "reporter": {
    "localAgentHostPort": "Jaeger-server-IP-address:6831"
  }
}
  1. 有关sampler对象的详细信息,请参阅Jaeger文档。

安装Zipkin插件

  1. 安装Zipkin插件。以下wget命令适用于x86-64 Linux系统:
$ cd /usr/local/lib$ wget -O - https://github.com/rnburn/zipkin-cpp-opentracing/releases/download/v0.5.2/linux-amd64-libzipkin_opentracing_plugin.so.gz | gunzip -c > /usr/local/lib/libzipkin_opentracing_plugin.so
  1. 为该插件创建一个JSON格式的配置文件,命名为/etc/zipkin/zipkin-config.json,并写入以下内容。此处使用Zipkin服务器的默认端口9411:
{  "service_name": "nginx",
  "collector_host": "Zipkin-server-IP-address",
  "collector_port": 9411
}
  1. 有关配置对象的详细信息,请参阅GitHub上的JSON架构。

配置NGINX Plus

在NGINX Plus主机上执行以下操作。

  1. 按照NGINX Plus 管理指南中的说明安装NGINX OpenTracing模块。
  2. 在NGINX Plus主配置文件(load_module)的主(顶层)上下文中添加以下/etc/nginx/nginx.conf指令:
load_module modules/ngx_http_opentracing_module.so;
  1. 将以下指令添加到NGINX Plus配置中。如果使用常规配置方案,请将这些指令放入名为/etc/nginx/conf.d/opentracing.conf的新文件中。此外,请确认以下include指令位于/etc/nginx/nginx.conf的http上下文中:
http {
    include /etc/nginx/conf.d/*.conf;
}
# Load a vendor tracer#opentracing_load_tracer /usr/local/libjaegertracing_plugin.so 
#                        /etc/jaeger/jaeger-config.json;
#opentracing_load_tracer /usr/local/lib/libzipkin_opentracing_plugin.so
#                        /etc/zipkin/zipkin-config.json;

# Enable tracing for all requests
opentracing on;

# Set additional tags that capture the value of NGINX Plus variables
opentracing_tag bytes_sent $bytes_sent;
opentracing_tag http_user_agent $http_user_agent;
opentracing_tag request_time $request_time;
opentracing_tag upstream_addr $upstream_addr;
opentracing_tag upstream_bytes_received $upstream_bytes_received;
opentracing_tag upstream_cache_status $upstream_cache_status;
opentracing_tag upstream_connect_time $upstream_connect_time;
opentracing_tag upstream_header_time $upstream_header_time;
opentracing_tag upstream_queue_time $upstream_queue_time;
opentracing_tag upstream_response_time $upstream_response_time;

#uncomment for debugging
# log_format opentracing '$remote_addr - $remote_user [$time_local] "$request" '
#                        '$status $body_bytes_sent "$http_referer" '
#                        '"$http_user_agent" "$http_x_forwarded_for" '
#                        '"$host" sn="$server_name" '
#                        'rt=$request_time '
#                        'ua="$upstream_addr" us="$upstream_status" '
#                        'ut="$upstream_response_time" ul="$upstream_response_length" '
#                        'cs=$upstream_cache_status';
#access_log /var/log/nginx/opentracing.log opentracing;
 
server {
    listen 9001;

    location / {
        # The operation name used for OpenTracing Spans defaults to the name of the
        # 'location' block, but uncomment this directive to customize it.
        #opentracing_operation_name $uri;

        # Propagate the active Span context upstream, so that the trace can be 
        # continued by the backend.
        opentracing_propagate_context;

        # Make sure that your Ruby app is listening on port 4567
        proxy_pass http://127.0.0.1:4567;
    }
}
  • The opentracing_load_tracer 指令用于启用跟踪器插件。根据需要,取消注释 Jaeger 或 Zipkin 对应的指令。
  • The opentracing_tag 指令使 NGINX Plus 变量可用作 OpenTracing 标签,并显示在跟踪器 UI 中。
  • 要调试OpenTracing活动,请取消注释log_format和access_log指令。如果要用此访问日志和日志格式替换NGINX的默认设置,请取消注释这些指令,然后将其中三处“opentracing”更改为“main”。另一种方法是仅记录端口9001上的流量所产生的OpenTracing活动。为此,请取消注释log_format和access_log指令,并将其移至server块中。
  • The server块为下一节所述的Ruby示例应用程序设置OpenTracing。
  1. 验证并重新加载NGINX Plus配置:
$ nginx -t$ nginx -s reload

设置示例 Ruby 应用

完成跟踪器和NGINX Plus配置后,我们创建一个示例Ruby应用,用于展示OpenTracing数据的形式。通过该应用,我们可以衡量NGINX Plus缓存对响应时间的改善程度。当应用收到如下针对GET的HTTP /请求时,会随机等待2至5秒后再响应。

$ curl http://NGINX-Plus-IP-address:9001/
  1. 安装并设置Ruby和Sinatra(一个用Ruby编写的开源Web应用程序库和领域特定语言,可替代其他Ruby Web应用程序框架)。
  2. 创建一个名为“app.rb”的文件,内容如下:
#!/usr/bin/ruby

require 'sinatra'

get '/*' do
    out = "<h1>Ruby simple app</h1>" + "\n"

    #Sleep a random time between 2s and 5s
    sleeping_time = rand(4)+2
    sleep(sleeping_time)
    puts "slept for: #{sleeping_time}s."
    out += '<p>some output text</p>' + "\n"

    return out
end
  1. 将app.rb设为可执行文件并运行:
$ chmod +x app.rb$ ./app.rb

跟踪未启用缓存时的响应时间

我们使用Jaeger和Zipkin来显示未启用缓存时NGINX Plus响应请求所需的时间。对于每个追踪工具,我们发送5个请求。

未启用缓存时的Jaeger输出

以下是Jaeger UI中显示的5个请求(按时间从近到远排列):

以下是Ruby应用控制台中显示的相同信息:

- -> /slept for: 3s. 
127.0.0.1 - - [07/Jun/2019: 10:50:46 +0000] "GET / HTTP/1.1" 200 49 3.0028
127.0.0.1 - - [07/Jun/2019: 10:50:43 UTC] "GET / HTTP/1.0" 200 49
- -> /
slept for: 2s. 
127.0.0.1 - - [07/Jun/2019: 10:50:56 +0000] "GET / HTTP/1.1" 200 49 2.0018 
127.0.0.1 - - [07/Jun/2019: 10:50:54 UTC] "GET / HTTP/1.0"1 200 49
- -> /
slept for: 3s. 
127.0.0.1 - - [07/Jun/2019: 10:53:16 +0000] "GET / HTTP/1.1" 200 49 3.0029 
127.0.0.1 - - [07/Jun/2019: 10:53:13 UTC] "GET / HTTP/1.0" 200 49
- -> /
slept for: 4s.
127.0.0.1 - - [07/Jun/2019: 10:54:03 +0000] "GET / HTTP/1.1" 200 49 4.0030 
127.0.0.1 - - [07/Jun/2019: 10:53:59 UTC] "GET / HTTP/1.0" 200 49
- -> /
slept for: 3s.
127.0.0.1 - - [07/Jun/2019: 10:54:11 +0000] "GET / HTTP/1.1" 200 49 3.0012
127.0.0.1 - - [07/Jun/2019: 10:54:08 UTC] "GET / HTTP/1.0" 200 49

在Jaeger UI中,点击第一个(最近的)请求以查看其详细信息,其中包括我们作为标签添加的NGINX Plus变量的值:

未启用缓存时的 Zipkin 输出

以下是Zipkin UI中的另外5个请求:

Ruby应用控制台上显示的相同信息:

- -> /slept for: 2s.
127.0.0.1 - - [07/Jun/2019: 10:31:18 +0000] "GET / HTTP/1.1" 200 49 2.0021 
127.0.0.1 - - [07/Jun/2019: 10:31:16 UTC] "GET / HTTP/1.0" 200 49
- -> /
slept for: 3s.
127.0.0.1 - - [07/Jun/2019: 10:31:50 +0000] "GET / HTTP/1.1" 200 49 3.0029 
127.0.0.1 - - [07/Jun/2019: 10:31:47 UTC] "GET / HTTP/1.0" 200 49
- -> /
slept for: 3s.
127.0.0.1 - - [07/Jun/2019: 10:32:08 +0000] "GET / HTTP/1.1" 200 49 3.0026 
127.0.0.1 - - [07/Jun/2019: 10:32:05 UTC] "GET / HTTP/1.0" 200 49
- -> /
slept for: 3s.
127.0.0.1 - - [07/Jun/2019: 10:32:32 +0000] "GET / HTTP/1.1" 200 49 3.0015 
127.0.0.1 - - [07/Jun/2019: 10:32:29 UTC] "GET / HTTP/1.0" 200 49
- -> /
slept for: 5s.
127.0.0.1 - - [07/Jun/2019: 10:32:52 +0000] "GET / HTTP/1.1" 200 49 5.0030 
127.0.0.1 - - [07/Jun/2019: 10:32:47 UTC] "GET / HTTP/1.0" 200 49

在Zipkin UI中,点击第一个请求以查看其详细信息,其中包括我们作为标签添加的NGINX Plus变量值:

使用缓存时的响应时间追踪

配置NGINX Plus缓存

我们通过在缓存中创建的opentracing.conf文件中添加指令来启用配置 NGINX Plus。

  1. 在 http 上下文中,添加以下 proxy_cache_path 指令:
proxy_cache_path /data/nginx/cache keys_zone=one:10m;
  1. 在server块中,添加以下proxy_cache和proxy_cache_valid指令:
proxy_cache one;
proxy_cache_valid any 1m;
  1. 验证并重新加载配置:
$ nginx -t$ nginx -s reload

启用缓存后的Jaeger输出

这是发出两次请求后的Jaeger UI。

首次响应(标记为13f69db)耗时4秒。NGINX Plus缓存了该响应。约15秒后再次发送请求时,由于响应来自NGINX Plus缓存,耗时不到2毫秒(ms)。

详细查看这两个请求,就能解释响应时间为何不同。对于第一个请求,upstream_cache_status为MISS,表示请求的数据不在缓存中。Ruby应用增加了4秒的延迟。

对于第2个请求,upstream_cache_status为HIT。由于数据来自缓存,Ruby应用无法增加延迟,响应时间不到2 ms。空的upstream_*值也表明上游服务器未参与此次响应。

启用缓存后的Zipkin输出

Zipkin UI中启用缓存的两个请求也呈现出类似的情况:

再次详细查看这两个请求,就能解释响应时间为何不同。第一个请求的响应未缓存(upstream_cache_status为MISS),而Ruby应用恰好也像Jaeger示例一样增加了4秒延迟。

在发出第二个请求之前,响应已被缓存,因此upstream_cache_status为HIT。

结论

NGINX OpenTracing模块支持跟踪NGINX Plus请求和响应,并可通过OpenTracing标签访问NGINX Plus变量。此模块还可与不同的跟踪器配合使用。

有关NGINX OpenTracing模块的更多详细信息,请访问GitHub上的NGINX OpenTracing模块仓库。

要在NGINX Plus中试用OpenTracing,立即开始30天免费试用,或联系我们,讨论您的使用场景。


分享
标签: F5 NGINX, Tech, 2019

相关博客文章

NGINX Plus R26 正式发布
NGINX | 2022/02/15

NGINX Plus R26 正式发布

NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。

使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
NGINX | 2022/02/10

使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击

gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。

Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
NGINX | 2021/09/13

Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划

了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。

NGINX Plus R19 正式发布
NGINX | 2019/09/03

NGINX Plus R19 正式发布

NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。

NGINX现已正式加入F5
NGINX | 2019/05/09

NGINX现已正式加入F5

NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。

使用NGINX和NGINX Plus实现高性能缓存
NGINX | 2016/08/24

使用NGINX和NGINX Plus实现高性能缓存

我将介绍NGINX在内容缓存和性能方面的工作原理,并分享一些控制NGINX内容缓存方式的技巧。