博客 | NGINX

NGINX 和 NGINX Plus 的 OpenTracing

NGINX-F5-horiz-black-type-RGB 的一部分
Mohamed Gougam 缩略图
穆罕默德·古加姆
2019 年 6 月 17 日发布

尽管微服务架构有很多好处,但它也带来了新的复杂性。 其中一个挑战是在处理请求时跟踪请求,数据在组成应用的所有微服务之间流动。 为此,人们发明了一种称为分布式(请求)跟踪的新方法,而OpenTracing是一套规范和标准 API,旨在指导分布式跟踪工具的设计和实施。

NGINX Plus Release 18(R18)中,我们将NGINX OpenTracing 模块添加到我们的动态模块存储库中(它已经作为第三方模块在 GitHub 上使用了几年)。 NGINX OpenTracing 模块的一大优势是,通过对 NGINX 和 NGINX Plus 进行分布式跟踪,您可以获得每个代理应用的跟踪数据,而无需单独对应用进行跟踪。

在此博客中,我们展示了如何为 NGINX 或 NGINX Plus 启用分布式请求跟踪(为简洁起见,从现在起我们将只提及NGINX Plus )。 我们为两种分布式跟踪服务(OpenTracing 术语中为tracersJaegerZipkin提供了说明。 (有关其他跟踪器的列表,请参阅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
  3. 验证您是否可以通过浏览器访问 Jaeger UI,网址为http:// Jaeger-server-IP-address :16686/ (16686 是 Jaeger 服务器的默认端口)。

安装 Zipkin 服务器

  1. 下载并运行 Zipkin 的 Docker 镜像(我们使用默认端口 9411)。

    $ docker run -d -p 9411:9411 openzipkin/zipkin
  2. 验证您是否可以通过浏览器访问 Zipkin UI,地址为http:// Zipkin-server-IP-address :9411/

安装和配置 Tracer 插件

在 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

    有关从源代码构建插件的说明可在GitHub上找到。

  2. 为插件创建一个 JSON 格式的配置文件,名为/etc/jaeger/jaeger-config.json ,内容如下。 我们使用 Jaeger 服务器的默认端口 6831:

    { “service_name”:“nginx”, “sampler”:{ “type”:“const”, “param”: 1 }, "记者": { "localAgentHostPort": “ Jaeger 服务器 IP 地址:6831” } }

    有关采样器对象的详细信息,请参阅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
  2. 为插件创建一个 JSON 格式的配置文件,名为/etc/zipkin/zipkin-config.json ,内容如下。 我们使用 Zipkin 服务器的默认端口 9411:

    { “服务名称”:“nginx”, “收集器主机”: “ Zipkin 服务器 IP 地址”、“collector_port”: 9411 }

    有关配置对象的详细信息,请参阅GitHub 上的 JSON 模式

配置NGINX Plus

在 NGINX Plus 主机上执行这些说明。

  1. 根据NGINX Plus 管理指南中的说明安装 NGINX OpenTracing 模块。

  2. 在主 NGINX Plus 配置文件 ( /etc/nginx/nginx.conf ) 的主(顶层)上下文中添加以下load_module指令:

    load_module 模块/ngx_http_opentracing_module.so;
  3. 将以下指令添加到 NGINX Plus 配置。

    如果您使用常规配置方案,请将指令放在名为/etc/nginx/conf.d/opentracing.conf的新文件中。 还要验证/etc/nginx/nginx.conf中的http上下文中是否出现以下include指令:

    http {
    包括 /etc/nginx/conf.d/*.conf;
    }
    • opentracing_load_tracer指令启用跟踪器插件。 根据需要取消注释 Jaeger 或 Zipkin 的指令。
    • opentracing_tag指令使 NGINX Plus 变量可用作跟踪器 UI 中出现的 OpenTracing 标签。
    • 要调试 OpenTracing 活动,请取消注释log_formataccess_log指令。 如果要用这个替换默认的 NGINX 访问日志和日志格式,请取消注释指令,然后将“ opentracing ”的三个实例更改为“ main ”。 另一个选择是仅记录端口 9001 上的流量的 OpenTracing 活动 - 取消注释log_formataccess_log指令并将它们移动到服务器块中。
    • 服务器块为下一节中描述的示例 Ruby应用设置了 OpenTracing。
    # 加载供应商跟踪器#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;
    
    # 为所有请求启用跟踪
    opentracing on;
    
    # 设置捕获 NGINX Plus 变量值的附加标签
    opentracing_tag bytes_sent $bytes_sent;
    opentracing_tag http_user_agent $http_user_agent;
    opentracing_tag request_time $request_time;
    opentracing_tag upper_addr $upstream_addr;
    opentracing_tag upper_bytes_received $upstream_bytes_received;
    opentracing_tag 上游缓存状态 $上游缓存状态;
    opentracing_tag 上游连接时间 $上游连接时间;
    opentracing_tag 上游头时间 $上游头时间;
    opentracing_tag 上游队列时间 $上游队列时间;
    opentracing_tag 上游响应时间 $上游响应时间;
    
    #取消注释以进行调试
    # 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 / {
    # 用于 OpenTracing Spans 的操作名称默认为
    # 'location' 块的名称,但取消注释此指令以对其进行自定义。
    #opentracing_operation_name $uri;
    
    # 将活动的 Span 上下文传播到上游,以便后端可以
    # 继续跟踪。
    opentracing_propagate_context;
    
    # 确保您的 Ruby 应用程序正在监听端口 4567
    proxy_pass http://127.0.0.1:4567;
    }
    }
  4. 验证并重新加载 NGINX Plus 配置:

    $ nginx -t $ nginx -s 重新加载

设置示例 Ruby 应用程序

有了跟踪器和 NGINX Plus 配置,我们创建了一个示例 Ruby 应用程序来展示 OpenTracing 数据的样子。 该应用程序让我们可以测量 NGINX Plus 缓存对响应时间的改善程度。 当应用程序收到类似以下 HTTP GET请求( / )的请求时,它会等待一段随机时间(2 到 5 秒之间)后再做出响应。

$ curl http:// NGINX-Plus-IP 地址:9001/
  1. 安装并设置RubySinatra (一种用 Ruby 编写的开源软件Web应用库和领域特定语言,可替代其他 Ruby Web应用框架)。

  2. 创建一个名为app.rb的文件,其内容如下:

    #!/usr/bin/ruby
    
    require 'sinatra'
    
    get '/*' do
    out = "<h1>Ruby simple app</h1>" + "\n"
    
    #在 2 秒到 5 秒之间随机休眠一段时间
    sleeping_time = rand(4)+2
    sleep(sleeping_time)
    puts "休眠时间:#{sleeping_time} 秒。"
    out += '<p>some output text</p>' + "\n"
    
    return out
    end
  3. 使app.rb可执行并运行它:

    $ chmod + x app.rb $ ./app.rb

不使用缓存跟踪响应时间

我们使用 Jaeger 和 Zipkin 来显示在未启用缓存的情况下 NGINX Plus 响应请求需要多长时间。 对于每个追踪者,我们发送 5 个请求。

Jaeger 的输出(无缓存)

以下是 Jaeger UI 中显示的五个请求(最新的请求在前面):

以下是 Ruby 应用程序控制台上的相同信息:

--> /睡眠时间: 3秒。 
127.0.0.1 - - [2019 年 6 月 7 日: 10:50:46 +0000] “GET / HTTP/1.1” 200 49 3.0028
127.0.0.1 - - [2019 年 6 月 7 日: 10:50:43 UTC] “GET / HTTP/1.0” 200 49
- -> /
休眠时间: 2秒。 
127.0.0.1 - - [2019 年 6 月 7 日: 10:50:56 +0000] “GET / HTTP/1.1” 200 49 2.0018 
127.0.0.1 - - [2019 年 6 月 7 日: 10:50:54 UTC] “GET / HTTP/1.0”1 200 49
- -> /
休眠时间: 3秒。 
127.0.0.1 - - [2019 年 6 月 7 日: 10:53:16 +0000] “GET / HTTP/1.1” 200 49 3.0029 
127.0.0.1 - - [2019 年 6 月 7 日: 10:53:13 UTC] “GET / HTTP/1.0” 200 49
- -> /
休眠时间: 4秒。
127.0.0.1 - - [2019 年 6 月 7 日: 10:54:03 +0000] “GET / HTTP/1.1” 200 49 4.0030 
127.0.0.1 - - [2019 年 6 月 7 日: 10:53:59 UTC] “GET / HTTP/1.0” 200 49
- -> /
休眠时间: 3秒。
127.0.0.1 - - [2019 年 6 月 7 日: 10:54:11 +0000] “GET / HTTP/1.1” 200 49 3.0012
127.0.0.1 - - [2019 年 6 月 7 日: 10:54:08 UTC] “GET / HTTP/1.0” 200 49

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

不使用缓存的 Zipkin 输出

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

Ruby 应用程序控制台上的相同信息:

--> /睡眠时间: 2秒。
127.0.0.1 - - [2019 年 6 月 7 日: 10:31:18 +0000] “GET / HTTP/1.1” 200 49 2.0021 
127.0.0.1 - - [2019 年 6 月 7 日: 10:31:16 UTC] “GET / HTTP/1.0” 200 49
- -> /
休眠时间: 3秒。
127.0.0.1 - - [2019 年 6 月 7 日: 10:31:50 +0000] “GET / HTTP/1.1” 200 49 3.0029 
127.0.0.1 - - [2019 年 6 月 7 日: 10:31:47 UTC] “GET / HTTP/1.0” 200 49
- -> /
休眠时间: 3秒。
127.0.0.1 - - [2019 年 6 月 7 日: 10:32:08 +0000] “GET / HTTP/1.1” 200 49 3.0026 
127.0.0.1 - - [2019 年 6 月 7 日: 10:32:05 UTC] “GET / HTTP/1.0” 200 49
- -> /
休眠时间: 3秒。
127.0.0.1 - - [2019 年 6 月 7 日: 10:32:32 +0000] “GET / HTTP/1.1” 200 49 3.0015 
127.0.0.1 - - [2019 年 6 月 7 日: 10:32:29 UTC] “GET / HTTP/1.0” 200 49
- -> /
休眠时间: 5秒。
127.0.0.1 - - [2019 年 6 月 7 日: 10:32:52 +0000] “GET / HTTP/1.1” 200 49 5.0030 
127.0.0.1 - - [2019 年 6 月 7 日: 10:32:47 UTC] “GET / HTTP/1.0” 200 49

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

使用缓存跟踪响应时间

配置 NGINX Plus 缓存

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

  1. http上下文中,添加此proxy_cache_path指令:

    proxy_cache_path /数据/nginx/cache keys_zone =一:10米;
  2. 服务器块中,添加以下proxy_cacheproxy_cache_valid指令:

    proxy_cache 一个;
    proxy_cache_valid 任意 1m;
  3. 验证并重新加载配置:

    $ nginx -t $ nginx -s 重新加载

使用缓存的 Jaeger 输出

这是两次请求后的 Jaeger UI。

第一个响应(标记为13f69db )耗时 4 秒。 NGINX Plus 缓存了响应,当大约 15 秒后重复请求时,响应所用时间不到 2 毫秒 (ms),因为它来自 NGINX Plus 缓存。

详细查看这两个请求可以解释响应时间的差异。 对于第一个请求, upstream_cache_statusMISS ,这意味着请求的数据不在缓存中。 Ruby 应用程序增加了 4 秒的延迟。

对于第二个请求, upstream_cache_statusHIT 。 由于数据来自缓存,Ruby 应用程序无法添加延迟,响应时间在 2 毫秒以下。 空的upstream_*值也表明上游服务器没有参与此响应。

带缓存的 Zipkin 输出

Zipkin UI 中对两个启用缓存的请求的显示描绘了类似的画面:

再次详细查看这两个请求可以解释响应时间的差异。 第一个请求的响应未被缓存( upstream_cache_statusMISS ),并且 Ruby 应用程序(巧合地)增加了与 Jaeger 示例中相同的 4 秒延迟。

在我们发出第二个请求之前,响应已被缓存,因此upstream_cache_statusHIT

结论

NGINX OpenTracing 模块支持跟踪 NGINX Plus 请求和响应,并使用 OpenTracing 标签提供对 NGINX Plus 变量的访问。 该模块还可使用不同的追踪器。

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

要尝试使用 NGINX Plus 的 OpenTracing,请立即开始30 天免费试用,或联系我们讨论您的用例


“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”