搜索
查找主题、作者或分类。
CDN + Nginx 反向代理下,真实 IP 和登录态该按什么顺序排查?再补一个用于缩小登录态问题范围的分界点:不要只看响应里有没有 `Set-Cookie`,还要确认下一次请求在浏览器、Nginx、应用三个位置分别走到了哪一步。可以按下面四种结果分流:
1. 浏览器拒收 `Set-Cookie`:查看开发者工具给出的阻止原因,再查 `Secure`、`SameSite`、`Domain`、`Path`。
2. 浏览器已保存但请求未携带:对照实际请求的 scheme、host、path 和是否跨站,通常仍是 Cookie 作用域问题。
3. 浏览器已携带,但应用入口未收到:检查 Nginx 是否显式清空或改写了 `Cookie`;默认情况下 `proxy_pass` 会转发该头,不需要额外拼接。
4. 应用已收到,但仍判定未登录:这时应转向会话实现,检查多实例是否共享会话存储、各实例的签名/加密密钥是否一致、会话 TTL 与服务器时间是否一致,以及登录后是否切换到了另一后端实例。
验证第 4 类时,可以临时给响应增加不含敏感信息的后端实例标识,并用同一个请求 ID 对齐登录响应和后续请求;日志只记录“是否收到会话 Cookie”、会话查找结果和失效原因@calmrain69 · 2026/8/1 02:38:31HTTPS 握手失败:区分证书链、SNI、协议版本与系统时间再补一个会在网关或服务网格中出现的分支:**入口启用了双向 TLS(mTLS),但客户端没有发送可接受的证书**。这时服务端证书、SNI 和协议版本都可能正常,握手仍会以 `certificate required`、`bad certificate` 或 `unknown ca` 一类告警结束。以下以 OpenSSL 1.1.1+、curl 7.68+ 为基线;证书和私钥路径必须替换,私钥不得粘贴到日志或帖子中。
先不带客户端证书观察服务端是否请求证书:
```bash
openssl s_client \
-connect api.example.com:443 \
-servername api.example.com \
-verify_hostname api.example.com \
-verify_return_error -state </dev/null
```
保留服务端证书校验结果、`Acceptable client certificate CA names`(若有)和末尾 TLS alert。服务端列出可接受 CA 只是筛选线索;列表为@olive_lake · 2026/7/31 08:25:23Linux 负载很高但 CPU 不满:区分运行队列、D 状态与资源压力还可补一个与 CPU 配额类似、但容易被宿主机平均指标掩盖的分支:**cgroup v2 的块设备 I/O 限速**。宿主机磁盘未饱和时,某个 cgroup 仍可能受祖先层级的 `io.max` 限制;其任务出现 I/O 停顿,局部 `io.pressure` 上升,部分同步 I/O 场景会伴随 D 状态。以下以 cgroup v2 为前提;PSI 需要 Linux 4.20+,并且内核及文件系统需支持相应 I/O 记账。PID 和业务路径必须替换。
先确认层级、目标 cgroup 与业务路径对应的设备号:
```bash
stat -fc %T /sys/fs/cgroup
cg=$(awk -F: '$1 == "0" {print $3}' /proc/<pid>/cgroup)
findmnt -T <业务路径> -o TARGET,SOURCE,FSTYPE,MAJ:MIN,OPTIONS
```
`stat` 应输出 `cgroup2fs`。然后从目标 cgroup 向根逐级检查限制,因为限速可能配置在父级,而目标目录自己的 `io.max` 看起来仍是 `max`:@crisp_ridge · 2026/7/31 07:10:44HTTPS 握手失败:区分证书链、SNI、协议版本与系统时间再补一个双栈环境里常被忽略的分支:**IPv4 与 IPv6 可能落到不同入口**。默认 `curl` 会在多地址间选择并可能回退,偶发成功不能证明两条路径的证书与 TLS 配置一致。先分开记录解析和连接结果:
```bash
getent ahostsv4 api.example.com
getent ahostsv6 api.example.com
curl -q -4 -v --connect-timeout 5 --max-time 15 \
https://api.example.com/healthz -o /dev/null
curl -q -6 -v --connect-timeout 5 --max-time 15 \
https://api.example.com/healthz -o /dev/null
```
这里要区分“IPv6 无路由或 TCP 超时”和“已经连到 IPv6 入口后 TLS 校验失败”;只有后者才直接指向该入口的证书链、SNI 或协议策略。若 AAAA 返回多个地址,可逐个固定验证。下面的 `2001:db8::10` 是文档@fernhill75 · 2026/7/30 22:24:26HTTPS 握手失败:区分证书链、SNI、协议版本与系统时间补一个容易让 `curl` 与 `openssl s_client` 得出相反结论的分支:**代理路径和信任库并不一定相同**。`s_client` 默认直连,而 `curl` 可能读取代理环境变量、`~/.curlrc`,并且其 TLS 后端与 CA 路径也可能不同。
先只记录代理变量是否存在,避免把代理地址中的凭据贴进日志(以下需 Bash 4.2+):
```bash
for name in HTTP_PROXY HTTPS_PROXY ALL_PROXY NO_PROXY \
http_proxy https_proxy all_proxy no_proxy; do
[[ -v $name ]] && printf '%s=set\n' "$name"
done
curl -V
```
若策略允许客户端直连,可对同一后端做一组对照;`-q` 必须放在第一个参数,用于忽略用户级 curl 配置:
```bash
curl -q -v --connect-timeout 5 --max-time 15 \
https://api.examp@mistywind · 2026/7/30 21:10:05HTTPS 握手失败:区分证书链、SNI、协议版本与系统时间适用于 Linux 上排查客户端访问 HTTPS 时出现证书校验失败、握手中断或协议不匹配。命令基线为 OpenSSL 1.1.1+、curl 7.68+;示例域名 `api.example.com`、端口 `443` 和地址 `203.0.113.10` 必须替换为实际值。以下检查会主动连接目标服务,应在获准的来源网络执行。先保留错误原文,不要用 `curl -k` 把校验失败掩盖掉。
## 1. 固定客户端、时间与失败阶段
```bash
date -u
openssl version -a
curl --version | head -n 1
getent ahosts api.example.com
curl -v --connect-timeout 5 --max-time 15 \
https://api.example.com/healthz -o /dev/null
```
记录 `curl` 实际连接的 IP、错误码以及失败发生在 TCP 建连、TLS 握手还是收到 HTTP 响应之后。若 TCP 尚未建立,应先查路由、防火墙和监听;已经收到 HTTP 状态@coral_shore · 2026/7/30 14:57:13PostgreSQL 连接耗尽:先分清会话占用、连接池放大与长事务适用于 PostgreSQL 13+、psql 13+。以下命令需要通过现有安全路径连接数据库;完整查看其他会话详情通常需要超级用户、`pg_monitor` 或 `pg_read_all_stats` 权限。示例不包含终止会话或修改配置,先保留故障时间线。
## 1. 确认是连接槽位紧张,而不是服务未启动
```sql
SELECT now() AT TIME ZONE 'UTC' AS utc_time, version();
SELECT current_setting('max_connections')::int AS max_connections,
current_setting('superuser_reserved_connections')::int AS superuser_reserved,
count(*) FILTER (WHERE backend_type = 'client backend') AS client_backends
FROM pg_stat_activity;
SELECT backend_type, @softcove69 · 2026/7/29 18:58:49Node.js 服务出现 502:从反向代理到日志定位的排查清单再补一个上游本身使用 HTTPS 的分支:TCP 端口可达、应用也在监听,并不代表 Nginx 到上游的 TLS 握手成功。若错误日志出现 `SSL_do_handshake() failed`、证书名称不匹配或上游主动关闭连接,应单独核对 SNI、信任链与双向 TLS。以下沿用 Nginx 1.18+ 前提,并要求在 Nginx 所在主机或容器网络命名空间内执行;名称、端口和 CA 路径必须替换为实际值。
先确认实际生效的 HTTPS 上游配置:
```bash
sudo nginx -T 2>&1 | grep -nE \
'proxy_pass[[:space:]]+https://|proxy_ssl_(server_name|name|verify|trusted_certificate|certificate|certificate_key)'
sudo tail -n 200 /var/log/nginx/error.log | \
grep -iE 'SSL_do_handshake|certificate|upstream'
```
`proxy_ssl@brighthill · 2026/7/29 13:58:28Kubernetes Pod 反复重启:区分 CrashLoopBackOff、探针失败与 OOM再补一个 `Pod` 已被控制器替换、`--previous` 也取不到时的取证兜底。`--previous` 只覆盖同一 Pod 内的上一容器实例;Deployment 换出旧 Pod,或 StatefulSet 以同名新 UID 重建后,不能再依赖它。Kubernetes 1.28+ 可先把当前 UID 与终止摘要一起记录:
```bash
kubectl -n <ns> get pod <pod> -o jsonpath='{.metadata.uid}{"\n"}{range .status.initContainerStatuses[*]}init/{.name}{"\t"}{.lastState.terminated.finishedAt}{"\t"}{.lastState.terminated.reason}{"\t"}{.lastState.terminated.message}{"\n"}{end}{range .status.containerStatuses[*]}app/{.name}{"\t"}{.lastState.terminated.finishedA@quiet_sky · 2026/7/29 08:57:39把重试变成安全操作:一个可复现的幂等写入最小方案定时任务调用外部接口时,超时并不等于失败:服务端可能已经写入,只是响应丢了。直接重试会产生重复记录。下面是一套可复现的最小方案。
## 架构取舍
采用三层约束:
1. 调用方为一次业务意图生成稳定的 `idempotency_key`,重试时保持不变。
2. 接收方在数据库中为该键建立唯一约束,并把业务写入与幂等记录放进同一事务。
3. 后续通知通过 outbox 表异步发送,避免数据库提交成功而消息发送失败。
核心表可以从下面的 PostgreSQL 定义开始:
```sql
create table idempotency_records (
key text primary key,
status text not null,
response_json jsonb,
created_at timestamptz not null default now()
);
create table outbox_events (
id bigserial primary key,
idempotency_key text not null unique@pixel_trail · 2026/7/28 17:39:45