尽管微服务架构有很多好处,但它也带来了新的复杂性。 其中一个挑战是在处理请求时跟踪请求,数据在组成应用的所有微服务之间流动。 为此,人们发明了一种称为分布式(请求)跟踪的新方法,而OpenTracing是一套规范和标准 API,旨在指导分布式跟踪工具的设计和实施。
在NGINX Plus Release 18(R18)中,我们将NGINX OpenTracing 模块添加到我们的动态模块存储库中(它已经作为第三方模块在 GitHub 上使用了几年)。 NGINX OpenTracing 模块的一大优势是,通过对 NGINX 和 NGINX Plus 进行分布式跟踪,您可以获得每个代理应用的跟踪数据,而无需单独对应用进行跟踪。
在此博客中,我们展示了如何为 NGINX 或 NGINX Plus 启用分布式请求跟踪(为简洁起见,从现在起我们将只提及NGINX Plus )。 我们为两种分布式跟踪服务(OpenTracing 术语中为tracers ) Jaeger和Zipkin提供了说明。 (有关其他跟踪器的列表,请参阅OpenTracing 文档。) 为了说明跟踪器提供的信息类型,我们比较了启用 NGINX Plus 缓存之前和之后的请求处理。
追踪器有两个基本组成部分:
第一步是安装并配置您选择的跟踪器的服务器。 我们为 Jaeger 和 Zipkin 提供了说明;请根据需要对它们进行调整,以适用于其他追踪器。
我们建议使用以下方法安装 Jaeger 服务器。 您还可以在步骤 1 中指定的 URL 下载 Docker 镜像。
导航到Jaeger 下载页面并下载 Linux 二进制文件(撰写本文时为jaeger-1.12.0-linux-amd64.tar )。
将二进制文件移动到/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
验证您是否可以通过浏览器访问 Jaeger UI,网址为http:// Jaeger-server-IP-address :16686/ (16686 是 Jaeger 服务器的默认端口)。
下载并运行 Zipkin 的 Docker 镜像(我们使用默认端口 9411)。
$ docker run -d -p 9411:9411 openzipkin/zipkin
验证您是否可以通过浏览器访问 Zipkin UI,地址为http:// Zipkin-server-IP-address :9411/ 。
在 NGINX Plus 主机上运行这些命令来安装 Jaeger 或 Zipkin 的插件。
安装 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上找到。
为插件创建一个 JSON 格式的配置文件,名为/etc/jaeger/jaeger-config.json ,内容如下。 我们使用 Jaeger 服务器的默认端口 6831:
{ “service_name”:“nginx”, “sampler”:{ “type”:“const”, “param”: 1 }, "记者": { "localAgentHostPort": “ Jaeger 服务器 IP 地址:6831” } }
有关采样器
对象的详细信息,请参阅Jaeger 文档。
安装 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
为插件创建一个 JSON 格式的配置文件,名为/etc/zipkin/zipkin-config.json ,内容如下。 我们使用 Zipkin 服务器的默认端口 9411:
{ “服务名称”:“nginx”, “收集器主机”: “ Zipkin 服务器 IP 地址”、“collector_port”: 9411 }
有关配置对象的详细信息,请参阅GitHub 上的 JSON 模式。
在 NGINX Plus 主机上执行这些说明。
根据NGINX Plus 管理指南中的说明安装 NGINX OpenTracing 模块。
在主 NGINX Plus 配置文件 ( /etc/nginx/nginx.conf ) 的主(顶层)上下文中添加以下load_module
指令:
load_module 模块/ngx_http_opentracing_module.so;
将以下指令添加到 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 标签。log_format
和access_log
指令。 如果要用这个替换默认的 NGINX 访问日志和日志格式,请取消注释指令,然后将“ opentracing
”的三个实例更改为“ main
”。 另一个选择是仅记录端口 9001 上的流量的 OpenTracing 活动 - 取消注释log_format
和access_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;
}
}
验证并重新加载 NGINX Plus 配置:
$ nginx -t $ nginx -s 重新加载
有了跟踪器和 NGINX Plus 配置,我们创建了一个示例 Ruby 应用程序来展示 OpenTracing 数据的样子。 该应用程序让我们可以测量 NGINX Plus 缓存对响应时间的改善程度。 当应用程序收到类似以下 HTTP GET
请求( / )的请求时,它会等待一段随机时间(2 到 5 秒之间)后再做出响应。
$ curl http:// NGINX-Plus-IP 地址:9001/
安装并设置Ruby和Sinatra (一种用 Ruby 编写的开源软件Web应用库和领域特定语言,可替代其他 Ruby Web应用框架)。
创建一个名为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
使app.rb可执行并运行它:
$ chmod + x app.rb $ ./app.rb
我们使用 Jaeger 和 Zipkin 来显示在未启用缓存的情况下 NGINX Plus 响应请求需要多长时间。 对于每个追踪者,我们发送 5 个请求。
以下是 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 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中创建的opentracing.conf文件中添加指令来启用缓存。
在http
上下文中,添加此proxy_cache_path
指令:
proxy_cache_path /数据/nginx/cache keys_zone =一:10米;
在服务器
块中,添加以下proxy_cache
和proxy_cache_valid
指令:
proxy_cache 一个;
proxy_cache_valid 任意 1m;
验证并重新加载配置:
$ nginx -t $ nginx -s 重新加载
这是两次请求后的 Jaeger UI。
第一个响应(标记为13f69db )耗时 4 秒。 NGINX Plus 缓存了响应,当大约 15 秒后重复请求时,响应所用时间不到 2 毫秒 (ms),因为它来自 NGINX Plus 缓存。
详细查看这两个请求可以解释响应时间的差异。 对于第一个请求, upstream_cache_status
是MISS
,这意味着请求的数据不在缓存中。 Ruby 应用程序增加了 4 秒的延迟。
对于第二个请求, upstream_cache_status
是HIT
。 由于数据来自缓存,Ruby 应用程序无法添加延迟,响应时间在 2 毫秒以下。 空的upstream_*
值也表明上游服务器没有参与此响应。
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模块 repo。
要尝试使用 NGINX Plus 的 OpenTracing,请立即开始30 天免费试用,或联系我们讨论您的用例。
“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”