Maison  >  Article  >  Tutoriel système  >  Suivi des liens Nginx pour l'architecture de microservices

Suivi des liens Nginx pour l'architecture de microservices

王林
王林original
2024-08-06 16:34:49735parcourir

Suivi des liens Nginx pour larchitecture de microservices

Dans la plupart des architectures de microservices, Nginx est essentiellement une fonctionnalité de couche d'accès couramment utilisée, nous espérons donc que l'ID de demande sera vérifié et renseigné à partir de la couche Nginx et imprimé dans le journal des demandes Nginx.

Conseils de lecture : Cet article ne fournit pas de solution complète pour le suivi des liens, mais fournit uniquement une solution de support pour le suivi des liens au niveau de la couche Nginx !

1 Introduction au contexte

La naissance des microservices a résolu de nombreux problèmes des applications monolithiques traditionnelles, tels qu'une mauvaise maintenabilité, une mauvaise évolutivité et une mauvaise flexibilité (comparaison à gros grain). Bien que l'architecture des microservices soit bonne, elle apporte également de nombreux défis, parmi lesquels le Dépannage est l'un des défis à résoudre. Alors, comment trouver la cause première d’une panne dans de nombreuses applications et instances ?

Sur la base des exigences ci-dessus, nous pouvons collecter et afficher de manière centralisée tous les journaux générés par chaque transaction dans chaque application (mais seulement si vous disposez de : Log Center). De cette façon, vous pouvez voir rapidement à quelle étape la transaction a échoué. Si cela est bien fait, vous pouvez également effectuer directement un développement secondaire et une analyse des données. Après avoir analysé les journaux et les défauts collectés, ils peuvent être affichés intuitivement avec une interface graphique.

Par exemple, vous pouvez afficher le diagramme de topologie des appels de microservice et utiliser des couleurs pour distinguer les défauts (comme le rouge couramment utilisé : indique une anomalie, le vert : normal, le jaune : avertissement). Ensuite, vous pouvez classer les défauts ou exceptions courants et faire un affichage convivial (pour parler franchement, il n'est pas nécessaire d'aller directement à la pile), tel que : NullPointerException : l'interface demande directement et de manière conviviale quelle ligne de code a lancé un pointeur nul. , et le paramètre d'entrée est What... (Ce n'est pas le sujet de cet article, donc je n'entrerai pas dans trop de bêtises. Je le présenterai en détail plus tard lorsque j'en aurai l'occasion).

Pour effectuer le suivi des liens de l'ensemble de l'architecture du microservice, nous espérons vivement qu'il y aura un identifiant de transaction global pour associer tous les journaux dès le premier point où une transaction entre dans le centre de microservices (pour le suivi des liens, un tel identifiant n'est certainement pas suffisant, mais c'est seulement cela qui est introduit ici). Bien entendu, l’idéal est de planifier les journaux front-end (tels que les journaux d’opérations, les flux de données, etc.).

2Nginx

Dans la plupart des architectures de microservices, Nginx est essentiellement une fonctionnalité de couche d'accès couramment utilisée, nous espérons donc que l'ID de demande sera vérifié et renseigné à partir de la couche Nginx et imprimé dans le journal des demandes Nginx. Voici seulement trois façons d'implémenter la méthode de production d'ID de transaction de la couche Nginx.

2.1 Option 2 : Épissage basé sur des variables intégrées

Dans les versions antérieures à 1.11.0, nous pouvons utiliser l'épissage pour assembler l'ID de demande. La configuration de référence est la suivante :

<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>;  
    }
}

Description du paramètre :

  • $pid : ID du processus de travail nginx
  • $connection : Le nombre d'identifiants de lien vers le serveur en amont
  • $bytes_sent : Nombre d'octets envoyés
  • $msec : L'heure actuelle, c'est-à-dire l'heure obtenue par cette variable, y compris les secondes et les millisecondes (divisées par .)
2.2 Option 3 : Implémentation basée sur le script LUA

Utilisez le UUID aléatoire généré par le système /dev/urandom. Le script de référence est le suivant :

<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 Solution 1 : basée sur la mise en œuvre de $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。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn