惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
A
About on SuperTechFans
The Last Watchdog
The Last Watchdog
A
Arctic Wolf
S
Schneier on Security
Cisco Talos Blog
Cisco Talos Blog
K
Kaspersky official blog
Spread Privacy
Spread Privacy
The Hacker News
The Hacker News
P
Proofpoint News Feed
Attack and Defense Labs
Attack and Defense Labs
NISL@THU
NISL@THU
AWS News Blog
AWS News Blog
Schneier on Security
Schneier on Security
TaoSecurity Blog
TaoSecurity Blog
H
Hacker News: Front Page
L
LangChain Blog
Y
Y Combinator Blog
T
Tenable Blog
Microsoft Security Blog
Microsoft Security Blog
L
Lohrmann on Cybersecurity
量子位
N
News and Events Feed by Topic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
The GitHub Blog
The GitHub Blog
云风的 BLOG
云风的 BLOG
W
WeLiveSecurity
Martin Fowler
Martin Fowler
Cloudbric
Cloudbric
S
SegmentFault 最新的问题
Project Zero
Project Zero
D
Darknet – Hacking Tools, Hacker News & Cyber Security
博客园 - 叶小钗
V
Vulnerabilities – Threatpost
小众软件
小众软件
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
腾讯CDC
博客园 - 聂微东
F
Full Disclosure
WordPress大学
WordPress大学
PCI Perspectives
PCI Perspectives
P
Privacy International News Feed
M
MIT News - Artificial intelligence
Forbes - Security
Forbes - Security
Blog — PlanetScale
Blog — PlanetScale
T
The Blog of Author Tim Ferriss
Webroot Blog
Webroot Blog
S
Security @ Cisco Blogs
Last Week in AI
Last Week in AI

mephisto.cc

修复rime-ice无法弹出候选框的问题 开机滚动字体显示优化 个人网站安全防护 树莓派上部署Vaultwarden 使用goaccess实时分析Caddy日志 个人网站监控 Hugo全站AVIF记 Linux下尝试使用Godot开发小游戏 Arch linux dae 透明代理 Airflow接管galler-dl下载任务 如何使用gallery-dl批量下载图像 Arch核显下如何愉快玩Dota2和CS2 Arch/labwc 环境网络相关设置 Rime添加dota2词库 Arch 重装记录 Supertuxkart iOS版终于发布了 打造自己的流媒体音乐服务 剪切板管理工具clipcat推荐 MangoHud性能监控 微信小程序开发记 Rofi试用 解决Arch下VSCode无法输入中文的问题 独立窗口管理器下无法录屏问题处理 上海市二手房成交数据监控 OpenLDAP监控 Arch linux如何顺畅连接蓝牙设备 使用Git和Ansible管理配置文件 Arch Linux SSL VPN 客户端配置 简单获取celery任务实时结果 Arch linux下iNode客户端的安装和使用方法 券商费率调整记 迷你主机组装记 Labwc更换定制皮肤 树莓派跑分流代理 实用自动代理配置示例 九年老鼠标复活记 Openvpn示例 Mac下如何旋转webp图片 如何隐藏Vscode中Markdown PDF插件的头部内容 解决Linux下网络配置无法变更保存的问题 labwc环境启用wlogout Ubuntu下新官方微信尝鲜 简单检测用户是否开启广告屏蔽 Atuin ZFS下卡顿问题解决 Wine安装64位微信 Fish 和 Atuin使用记 Fastapi简单实现临时下载链接 Fastapi微信公众号开发简要 Hugo根据语种展示不同内容 如何修复Waybar微信图标错误 信封加密简要 Linux环境下维护公众号记录 快速隐藏和呼出终端 Wayland环境自动切换壁纸 SuperTuxKart 试玩 简单抓取雪球股票快讯 为什么你的kill命令不能列出信号表 Wine安装微信保姆教程 Hysteria科学上网简要 Ubuntu 23.10 钉钉无法启动解决方法 网站导航栏防止插入Adsense自动广告 Linux环境按键检测 Hugo文末添加最后修改时间 Wayland环境ksnip无法复制问题解决 我眼中的股票市场 Caddy简单图片防盗链 greetd和regreet使用教程 Wayland环境下截图加后期修改 Wayland 环境下gif录屏 Firefox的一些有趣功能 Ubuntu 切换系统语言 Firefox 标题栏高度调整 网站添加回到顶部功能 Hugo自定义字体 Labwc 便捷配置 Wofi使用教程 窗口管理器labwc使用记 文件共享软件Dufs推荐 Hugo静态站点接入Adsense广告 Fcitx5配置详解 Ubuntu安装chrome的方法总结 一种Xterm.js的全屏方案 Google网址收录api Python示例 手机听离线音乐 Snipe it资产导入 应用启动器yofi使用配置 Snipe it资产管理系统安装使用 Ubuntu开机启动加速 Vue3 vite TypeScript跨域等相关设置 Ubuntu手动升级Libreoffice Ubuntu设置alacritty为默认终端 简体文章批量转换为繁体 使用Inkscape调整svg图片大小 实用命令 使用mitmproxy给手机app抓包 Python中rstrip方法细解 Github同主机多仓库部署deploy key问题处理 Linux安装最新版本Python KeePassXC使用教程 Ubuntu 22.10连接蓝牙耳机报错br-connection-profile-unavailable解决方法
Nginx日志$upstream_addr多个值
2022-09-01 · via mephisto.cc

最近在排查一个线上问题的时候,发现 nginx 日志$upstream_addr 字段居然返回了 2 个值,形如"192.168.1.1:80, api-servers",其中 api-servers 是指代的是你的 upstream 后面接 group name,部分只有一个值"api-servers"。正常情况下,这个地方应该是类似“192.168.1.1:80”这样,即一个请求落到一个后端服务。

查询官方文档:

$upstream_addr

keeps the IP address and port, or the path to the UNIX-domain socket of the upstream server. If several servers were contacted during request processing, their addresses are separated by commas, e.g. “192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock”. If an internal redirect from one server group to another happens, initiated by “X-Accel-Redirect” or error_page, then the server addresses from different groups are separated by colons, e.g. “192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock : 192.168.10.1:80, 192.168.10.2:80”. If a server cannot be selected, the variable keeps the name of the server group.

细读上面的文档,当请求尝试链接了多个后端服务器的时候,上述逗号分割多值记录的情况就会发生,冒号分割是另外一种状况,这里不讨论。当值为 server group name 的时候,“If a server cannot be selected” 这英文表意不明,写这个文档的人英文应该不是母语,是所有后端不可用,还是在默认限定的选择数目内都不可用,有知道的高手可以探讨下。总之,如果你的服务是注册到 upstream 里面的,服务池里面的服务,此时应该是不可用了,要自己去排错,多值记录给了你个线索。

在我们的场景中,是使用 consul 注册服务的,判定为某个机房的 consul 集群异常了,导致旧的服务没有被摘除,新的也没有及时更新,落到旧服务的请求没有可用的 server, 返回 502 状态码。

昨天对这个有疑问,今天来测试验证。

1. Nginx 配置

 1    ➜  cat /etc/nginx/conf.d/test.com.conf
 2    upstream backend-servers{
 3            server 127.0.0.1:9527;
 4            server 127.0.0.1:9528;
 5            server 127.0.0.1:9529;
 6            server 127.0.0.1:9530;
 7            server 127.0.0.1:9531;
 8            server 127.0.0.1:9532;
 9            server 127.0.0.1:9533;
10            server 127.0.0.1:9534;
11            server 127.0.0.1:9535;
12            server 127.0.0.1:9536;
13            server 127.0.0.1:9537;
14            server 127.0.0.1:9538;
15            server 127.0.0.1:9539;
16            server 127.0.0.1:9540;
17            server 127.0.0.1:9541;
18            server 127.0.0.1:9542;
19            server 127.0.0.1:9543;
20            server 127.0.0.1:9544;
21            server 127.0.0.1:9545;
22            server 127.0.0.1:9546;
23            server 127.0.0.1:9547;
24            server 127.0.0.1:9548;
25            server 127.0.0.1:9549;
26            server 127.0.0.1:9550;
27            server 127.0.0.1:9551;
28            server 127.0.0.1:9552;
29            server 127.0.0.1:9552;
30            server 127.0.0.1:9553;
31            server 127.0.0.1:9554;
32            server 127.0.0.1:9555;
33            server 127.0.0.1:9556;
34            server 127.0.0.1:9557;
35            server 127.0.0.1:9558;
36            server 127.0.0.1:9559;
37            server 127.0.0.1:9560;
38            server 127.0.0.1:9561;
39            server 127.0.0.1:9562;
40    }
41    server {
42            listen 80;
43            server_name test.com;
44
45            access_log /data/log/test.com.log access;
46
47            location /{
48                    proxy_pass http://backend-servers;
49            }
50    }

2. 用 Flask 模拟运行 backend-server

 1test cat server1.py
 2    from flask import Flask
 3
 4    app = Flask(__name__)
 5
 6    @app.route("/")
 7    def hello_world():
 8        return "<p>Hello, 9527!</p>"
 9
10    if __name__ == '__main__':
11        app.run(host="0.0.0.0", port=9527)
12
13test cat server2.py
14    from flask import Flask
15
16    app = Flask(__name__)
17
18    @app.route("/")
19    def hello_world():
20        return "<p>Hello, 9528!</p>"
21
22    if __name__ == '__main__':
23        app.run(host="0.0.0.0", port=9528)
24``
25
26如下图所示
27
28![flask server](/images/flask-server.avif)
29
30### 3. 测试抓包查看日志验证
31
32- 用命令 curl 测试
33
34```shell
35curl -H "Host:test.com" http://127.0.0.1
  • tcpdump 抓包看 nginx 是否会连接失效的 backend-server
1sudo tcpdump -i lo port 9528
  • 查看日志结果

    nginx upstream test

    通过启动关停 flask server, 再查看 nginx $upstream_addr 字段的值,看看 nginx 不同情况记录什么内容。

结论,当有一个可用的服务的时候,upstream_addr 记录的是这个可用后端的 ip:port; 非动态注册(测试用例就是写死的 upstream),Nginx 会去重试连接那些失效 server,此时 upstream_addr 显示多个值,尝试链接了多少个,就逗号分割记录多少个; 当关停所有 flask 后,upstream_addr 显示为“backend-servers”,即 upstream 后面定义的名字,出现这个,表明没有一个可用的后端服务,问题大了,服务彻底不可啦!