今天公司項目遇到一個奇怪的問題,記錄一下。
注: 數據已經過脫敏處理,未暴露公司具體的IP等數據。
TLDR; 項目簡單介紹
用 Vue + ElementUI 實現的后台項目(以下簡稱:a-project),不包含 Node 聚合層,前端開發完成后將打包生成的 dist
文件夾上傳到服務器的某目錄下,由 Nginx 作為 Web 服務器驅動頁面。
同時 Nginx 實現了反向代理,隱藏了服務器真實的 IP 地址。
Nginx 默認配置為 /etc/nginx/nginx.conf
文件,摘錄如下:
# /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
從上面配置可以獲取到以下信息:
- 錯誤日志存儲在
/var/log/nginx/error.log
文件中; - 訪問日志存儲在
/var/log/nginx/access.log
文件中; - 監聽80端口,子站的配置存儲在
/etc/nginx/default.d
目錄下在的*.nginx
文件中;
a-project 的 Nginx 配置文件為:/etc/nginx/default.d/project-a.homedo.com.conf
,關鍵信息摘錄如下:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server
{
listen 1024;
server_name a-project.homedo.com;
index index.html index.htm;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
root /home/xxxx/projectA;
location ^~/a-api/{
add_header 'Access-Control-Allow-Origin' '*';
proxy_pass https://a-api.homedo.com/;
}
# <======= 注:此處 b-api 的轉發突然失敗
location ^~/b-api/ {
add_header 'Access-Control-Allow-Origin' '*';
proxy_pass http://b-api.homedo.com/;
}
location ^~/c-api/ {
add_header 'Access-Control-Allow-Origin' '*';
proxy_pass http://c-api.homedo.com/;
}
# ... 其他配置
}
問題描述
從上面的 Nginx 配置可以看到 project-a 使用到了 a-api
、b-api
、c-api
三個子域名的接口,測試反饋說項目中某些接口突然報錯500,經排查發現:
http://b-api.homedo.com
通過 Swagger 可以正常訪問,通過 PostMan 也可以正常訪問;- 訪問
http://a-project.homedo.com
訪問b-api
下的接口,集體報錯:500; - 和用戶權限無關,所有用戶必現;
- 和接口權限無關,所有
b-api
下的接口均報錯;
排查過程
STEP1
基本鎖定問題是 b-api
轉發失敗,Nginx 錯誤日志 /var/log/nginx/error.log
為空,Nginx 並沒有捕獲到這些報錯,access.log
也沒有有用的信息。
在 project-a
所在服務器 xx.xx.xx.100
訪問 http://a-project.homedo.com/areas/all
接口發現報錯:
在另一台服務器(xx.xx.xx.200
)訪問 http://a-project.homedo.com/areas/all
接口發現可以正常拿到結果。
注: 此處正常是因為 xx.xx.xx.200 從未訪問過,目標域名未被 DNS 緩存。
STEP2
詢問其他同事發現好多項目都遇到了同樣的問題,原因是運維改了域名的解析地址。
解決辦法:
- 重啟服務器
- 清空DNS緩存
問題原因
首先梳理一下訪問路徑:
- 用戶訪問了系統,
a-project.homedo.com
,DNS將域名解析到xx.xx.xx.100
; a-project.homedo.com
調用a-api.homedo.com
時,DNS會解析到服務器xx.xx.xx.101
;a-project.homedo.com
調用b-api.homedo.com
時,DNS會解析到服務器xx.xx.xx.102
;a-project.homedo.com
調用c-api.homedo.com
時,DNS會解析到服務器xx.xx.xx.103
;
(也許是因為機器遷移)運維將 b-api.homedo.com
解析地址改動為 xx.xx.xx.202
后,以上第 3 步由於機器緩存了DNS解析記錄,所以報錯500。
總結
1. 怎么清除 DNS 緩存?
service nscd restart
2. 為什么重啟后問題就解決了?
nscd 服務被重啟了。
3. 什么是 nscd?
nscd(Name Service Cache Daemon)是一種能夠緩存 passwd、group、hosts 的本地緩存服務,分別對應三個源 /etc/passwd、/etc/hosts、/etc/resolv.conf。其最為明顯的作用就是加快 DNS 解析速度,在接口調用頻繁的內網環境建議開啟。
4. 正向代理和反向代理?
- 正向代理隱藏了用戶的真實地址;
- 反向代理隱藏了服務器的真實地址;