記一次Nginx反向代理500的排查記錄


今天公司項目遇到一個奇怪的問題,記錄一下。

注: 數據已經過脫敏處理,未暴露公司具體的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 {
        }
    }
}  

從上面配置可以獲取到以下信息:

  1. 錯誤日志存儲在 /var/log/nginx/error.log 文件中;
  2. 訪問日志存儲在 /var/log/nginx/access.log 文件中;
  3. 監聽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' '*';![20200621094514.jpg](https://poppython.oss-cn-beijing.aliyuncs.com/pdf_report/92f83018-1fb7-45f3-9f1f-de34eede661f__20200621094514.jpg)
        proxy_pass http://c-api.homedo.com/;
    }
    # ... 其他配置
}

問題描述

從上面的 Nginx 配置可以看到 project-a 使用到了 a-apib-apic-api 三個子域名的接口,測試反饋說項目中某些接口突然報錯500,經排查發現:

  1. http://b-api.homedo.com 通過 Swagger 可以正常訪問,通過 PostMan 也可以正常訪問;
  2. 訪問 http://a-project.homedo.com 訪問 b-api 下的接口,集體報錯:500;
  3. 和用戶權限無關,所有用戶必現;
  4. 和接口權限無關,所有 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 接口發現報錯:

20200621094514.jpg

在另一台服務器(xx.xx.xx.200)訪問 http://a-project.homedo.com/areas/all 接口發現可以正常拿到結果。

注: 此處正常是因為 xx.xx.xx.200 從未訪問過,目標域名未被 DNS 緩存。

STEP2

詢問其他同事發現好多項目都遇到了同樣的問題,原因是運維改了域名的解析地址。

解決辦法:

  1. 重啟服務器
  2. 清空DNS緩存

問題原因

首先梳理一下訪問路徑:

  1. 用戶訪問了系統,a-project.homedo.com,DNS將域名解析到 xx.xx.xx.100
  2. a-project.homedo.com 調用 a-api.homedo.com 時,DNS會解析到服務器 xx.xx.xx.101
  3. a-project.homedo.com 調用 b-api.homedo.com 時,DNS會解析到服務器 xx.xx.xx.102
  4. 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. 正向代理和反向代理?

  • 正向代理隱藏了用戶的真實地址;
  • 反向代理隱藏了服務器的真實地址;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM