搜索
首页系统教程LINUX微服务架构之Nginx链路追踪

微服务架构之Nginx链路追踪

Aug 06, 2024 pm 04:34 PM
linuxlinux教程红帽linux系统linux命令linux认证红帽linuxlinux视频

微服务架构之Nginx链路追踪

在大部分的微服务架构中,Nginx基本是常用的接入层设施,所以我们希望请求ID从Nginx层进行校验填充,并且打印在Nginx的请求日志中。

阅读提示:本文不提供链路追踪的完整解决方案,只提供Nginx层对链路追踪的支持方案!

1 背景介绍

微服务的诞生,解决了传统单体应用的很多问题,如可维护性差、扩展性差和灵活性差等问题(粗粒比较)。微服务架构虽好,但同时也带来了很多挑战,其中 故障排查 就是其需要解决的挑战之一。那么,如何在很多个应用和实例中找到故障发生的根源呢?

基于以上需求,我们可以将每一笔交易在各个应用中产生的所有日志,进行集中式收集与展示(但前提是你得有:日志中心)。这样就可以很快看出交易是在哪一步出的故障。如果做得好,还可以直接进行二次开发与数据分析,将收集的日志和出现的故障进行分析后,用图形界面很直观的进行展示。

比如,可以展示出微服务调用的拓扑图,使用颜色进行区分故障(如常用红:表示异常、绿:正常、黄:警告)。接着可以将常出现的故障或异常进行分类后做出友好型的展示(说白了就不用直接上堆栈),如:NullPointerException:则界面直接友好型的提示哪一行代码抛了空指针,输入参数是什么……(这不是该篇的重点哈,废话不多说了,后续有机会再详细介绍)。

要做整个微服务架构的链路追踪,肯定是希望从交易进入微服务中心的第一个点就开始有一个全局的交易ID来关联所有日志(链路追踪,这么一个ID肯定是不够的,但这里只介绍这个哈)。当然最理想的肯定是希望把前端的日志(如操作日志、数据流等)也规划进行。

2 Nginx

在大部分的微服务架构中,Nginx基本是常用的接入层设施,所以我们希望请求ID从Nginx层进行校验填充,并且打印在Nginx的请求日志中。这里只提供三种方式来实现Nginx层的交易ID生产方式。

2.1 方案二:基于内置变量拼接

在1.11.0之前的版本,我们可以采用拼接的方式来组装请求ID。参考配置如下:

<span class="hljs-section">server</span> {
    <span class="hljs-comment"># 定义$request_trace_id的值,在1.11.0之前,我们可以使用类似的方式声明</span>
    <span class="hljs-comment"># 只要能确保其值出现重复的可能性尽可能的小即可。 </span>
    <span class="hljs-attribute">set</span> <span class="hljs-variable">$request_trace_id</span> trace-id-<span class="hljs-variable">$pid</span>-<span class="hljs-variable">$connection</span>-<span class="hljs-variable">$bytes_sent</span>-<span class="hljs-variable">$msec</span>;
    <span class="hljs-attribute">location</span> / {
        <span class="hljs-comment"># ……</span>
        <span class="hljs-comment"># 将此trace_id传递给后端的server,通过header方式,此后我们既可以在环境中获取此header  </span>
        <span class="hljs-attribute">proxy_set_header</span> X-Request-Id <span class="hljs-variable">$request_trace_id</span>;  
    }
}

参数说明

  • $pid:nginx worker进程号
  • $connection:与upstream server链接id数
  • $bytes_sent:发送字节数
  • $msec:当前时间,即此变量获取的时间,包含秒、毫秒数(中间以.分割)
2.2 方案三:基于LUA脚本实现

利用系统/dev/urandom 生成的随机 UUID 。参考脚本如下:

<span class="hljs-comment">---</span>
 <span class="hljs-comment">--- UUID</span>
 <span class="hljs-comment">--- Created by lry.</span>
 <span class="hljs-comment">--- DateTime: 2018/2/25 下午7:38</span>
 <span class="hljs-comment">--- Describe: 用系统/dev/urandom生成的随机uuid</span>
 <span class="hljs-comment">---</span>
 <span class="hljs-keyword">local</span> template =<span class="hljs-string">"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"</span>
 <span class="hljs-keyword">local</span> d = <span class="hljs-built_in">io</span>.open(<span class="hljs-string">"/dev/urandom"</span>, <span class="hljs-string">"r"</span>):read(<span class="hljs-number">4</span>)
 <span class="hljs-built_in">math</span>.randomseed(<span class="hljs-built_in">os</span>.time() + d:byte(<span class="hljs-number">1</span>) + (d:byte(<span class="hljs-number">2</span>) * <span class="hljs-number">256</span>) + (d:byte(<span class="hljs-number">3</span>) * <span class="hljs-number">65536</span>) + (d:byte(<span class="hljs-number">4</span>) * <span class="hljs-number">4294967296</span>))
<span class="hljs-keyword">local</span> uuid=<span class="hljs-built_in">string</span>.gsub(template, <span class="hljs-string">"x"</span>,
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(c)</span></span>
    <span class="hljs-keyword">local</span> v = (c == <span class="hljs-string">"x"</span>) <span class="hljs-keyword">and</span> <span class="hljs-built_in">math</span>.random(<span class="hljs-number">0</span>, <span class="hljs-number">0xf</span>) <span class="hljs-keyword">or</span> <span class="hljs-built_in">math</span>.random(<span class="hljs-number">8</span>, <span class="hljs-number">0xb</span>)
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">string</span>.format(<span class="hljs-string">"%x"</span>, v)
  <span class="hljs-keyword">end</span>)
<span class="hljs-keyword">return</span> uuid
2.3 方案一:基于  $request_id  实现

Nginx在 1.11.0版本中就提供了内置变量 $request_id ,其原理就是生成32位的随机字符串,虽不能比拟UUID的概率,但32位的随机字符串的重复概率也是微不足道了,所以一般可视为UUID来使用即可。参考配置如下:

<span class="hljs-comment"># Nnginx代理默认会把header中参数的 "_" 下划线去掉,所以后台服务器后就获取不到带"_"线的参数名</span>
<span class="hljs-attribute">underscores_<span class="hljs-keyword">in</span>_headers</span> <span class="hljs-literal">on</span>;

<span class="hljs-comment"># 设定日志格式</span>
<span class="hljs-attribute"><span class="hljs-built_in">log</span>_format</span> main  \<span class="hljs-string">'<span class="hljs-variable">$remote_addr</span> - <span class="hljs-variable">$remote_user</span> [<span class="hljs-variable">$time_local</span>] "<span class="hljs-variable">$request</span>" \'
                 \'<span class="hljs-variable">$status</span> <span class="hljs-variable">$body_bytes_sent</span> "<span class="hljs-variable">$http_referer</span>" <span class="hljs-variable">$upstream_http_request_id</span> \'
                 \'"<span class="hljs-variable">$http_user_agent</span>" "<span class="hljs-variable">$http_x_forwarded_for</span>"\';

server {
    location / {
        <span class="hljs-comment"># 如果请求头中已有该参数,则获取即可;如果没有,则使用</span><span class="hljs-variable"><span class="hljs-comment">$request_id</span></span><span class="hljs-comment">进行填充</span>
        <span class="hljs-built_in">set</span> <span class="hljs-variable">$temp_request_id</span> <span class="hljs-variable">$http_x_request_id</span>;
        <span class="hljs-keyword">if</span> (<span class="hljs-variable">$temp_request_id</span> = "") {
            <span class="hljs-built_in">set</span> <span class="hljs-variable">$temp_request_id</span> <span class="hljs-variable">$request_id</span>;
        }
        <span class="hljs-comment"># 屏蔽掉原来的请求头参数</span>
        proxy_<span class="hljs-built_in">set</span>_header  x_request_id        "";
        <span class="hljs-comment"># 设置向后转发的请求头参数</span>
        proxy_<span class="hljs-built_in">set</span>_header  X-Request-Id        <span class="hljs-variable">$temp_request_id</span>;
    }
}
</span>
3 最佳实践

生成交易ID的方式有很多种,但希望使用者结合自身实际情况进行合理取舍,而不要盲目的追求ID的唯一性、可读性和时序性等等。

比如,ID具有时序性虽然有一定的好处,但实际的架构根本没有去使用该时序性,则没必要花大量的精力和做出大量的开发,去实现一个有时序性的交易ID。又比如,觉得UUID可读性太差,从而花了很多成本去开发一个具有一定含义的交易ID(如前几位表示什么意思,多少位到多少位又表示什么意思之类的),开发出来后,实际架构根本没有去解读该ID的地方,则浪费了成本。

但也不是所有人都直接使用UUID就能满足的,比如我需要考虑日志的容量,则可以考虑适当缩减ID的长度(每个ID缩减10个字符串,每笔交易就可能少几百或几千个字符串,再往上规划,还是可以减少一些日志容量的)。

最后,如果有考虑想收集前端的日志的童鞋,建议交易ID就不要使用Long型,因为前端可能会有损失精度的问题。同时也建议使用 $request_id  来填充交易ID。

以上是微服务架构之Nginx链路追踪的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
与硬化Windows系统相比,硬化Linux系统的考虑因素是什么?与硬化Windows系统相比,硬化Linux系统的考虑因素是什么?May 10, 2025 am 12:08 AM

Linux和Windows系统加固的策略各有不同:1.Linux加固包括最小化安装、用户和权限管理、防火墙配置和使用SELinux或AppArmor。2.Windows加固策略涉及启用WindowsDefender、配置组策略、使用Windows更新和补丁管理。

仓库:用于轻松处理Flatpak应用的GUI仓库:用于轻松处理Flatpak应用的GUIMay 09, 2025 am 11:30 AM

用于轻松Flatpak管理的GUI:介绍仓库 仅使用命令行管理越来越多的FlatPak应用程序集合可能会很麻烦。 输入仓库,这是一种用户友好的图形接口,旨在简化flatpak a

8个强大的Linux命令来识别硬盘驱动器瓶颈8个强大的Linux命令来识别硬盘驱动器瓶颈May 09, 2025 am 11:03 AM

本文为识别和解决Linux系统中的硬盘驱动器瓶颈提供了综合指南。 经验丰富的服务器管理员会发现这特别有用。缓慢的磁盘操作会严重影响应用程序性能,

Linux用户的4个最佳QR码生成器Linux用户的4个最佳QR码生成器May 09, 2025 am 10:27 AM

Linux系统下的高效二维码生成工具 在当今数字世界中,二维码已成为快速便捷地共享信息的一种方式,从URL、文本、联系人、Wi-Fi凭证,甚至支付信息,二维码都简化了数据访问。 Linux用户可以使用多种工具高效地创建二维码。让我们来看看一些可在Linux系统上直接使用的流行二维码生成器。 QRencode QRencode是一个轻量级的命令行工具,用于在Linux上生成二维码,它以其简单性和效率而广受好评,深受偏爱直接方法的Linux用户的欢迎。 使用QRencode,您可以为URL、

基本操作系统8:用于MACOS和Windows的用户友好型Linux基本操作系统8:用于MACOS和Windows的用户友好型LinuxMay 09, 2025 am 10:19 AM

基本操作系统8 Circe:一种流畅,时尚的Linux体验 基于Ubuntu的Linux发行版,Elementary OS已从简单的主题包演变为一个完整的独立操作系统。 以其用户友好的界面而闻名

每个机器学习工程师的40个Linux命令每个机器学习工程师的40个Linux命令May 09, 2025 am 10:06 AM

掌握Linux对于任何机器学习(ML)工程师至关重要。 它的命令行界面提供了无与伦比的灵活性和控制,简化工作流程并提高了生产力。本文概述了必需的Linux命令,FO解释说

Arch Linux备忘单:初学者的基本命令Arch Linux备忘单:初学者的基本命令May 09, 2025 am 09:54 AM

Arch Linux:初学者的命令行备忘单 Arch Linux提供了无与伦比的控制,但对于新移民来说可能会令人生畏。该备忘单提供了自信管理系统的必要命令。 系统信息和更新 这些com

如何在Linux上安装用于机器学习的Scikit-Learn如何在Linux上安装用于机器学习的Scikit-LearnMay 09, 2025 am 09:53 AM

本指南提供了在Linux Systems上安装和使用Scikit-Learn机器学习库的全面演练。 Scikit-Learn(Sklearn)是一个功能强大的开源python库,为各种机器提供多种工具L

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境