Nginx 的应用场景

2024-10-13· 25min

仅记录实际投产的场景,持续更新...

#HTTP Basic Authentication

#1. 安装
htpasswd

# CentOS
$ yum install httpd-tools -y

#2. 生成账密

# -b 允许传递密码,-m 使用 MD5 加密
$ htpasswd -b -m /etc/nginx/file.htpasswd ${yourName} ${yourPassword}

#3. 配置
auth_basic

server {
  listen 80;
  server_name example.com;

  location / {
    auth_basic "Login Authentication";
    auth_basic_user_file /etc/nginx/file.htpasswd;

    ...
  }
}

#持久连接/连接复用

upstream server_api {
  server 127.0.0.1:8899;
  keepalive 50;
}

server {
  listen 80;
  server_name api.example.com;

  location ~ ^/(xxxxx.*)/api/ {
    proxy_pass http://server_api;
    # 默认是 HTTP/1.0,显性配置 HTTP/1.1 并结合 upstream#keepalive 开启长链接复用
    proxy_http_version 1.1;
    # 避免上游服务器根据 HTTP/1.0 的要求主动关闭连接
    proxy_set_header Connection "";
  }
}

#请求限流

# $binary_remote_addr -> 客户端的二进制 IP 地址
# zone=limitzone:500m -> 内存区域,名为 limitzone,大小为 500MB
# rate=10r/s -> 每个 IP 地址每秒最多允许 10 个请求
limit_req_zone $binary_remote_addr zone=limitzone:500m rate=10r/s;
server {
  server_name api.example.com;
  location / {  
    # burst=5 -> 允许最多 5 个额外请求超出正常限速
    # nodelay -> 突发请求情况下,这 5 个请求将立即被处理,不会被延迟
    limit_req zone=limitzone burst=5 nodelay;
    proxy_pass http://127.0.0.1:8899;
  }
}

#自定义访问日志

log_format ApiLogFormat '$remote_addr - [$time_local] "$request" - $status '
                        'querykey: "$arg_querykey" '
                        'request_time: "$request_time" '
                        'api_cache_status: "$upstream_cache_status" ';

server {
  server_name api.example.com;
  access_log /etc/nginx/logs/api.example.com-access-$year$month$day$hour.log ApiLogFormat;
  location / {
    proxy_pass http://127.0.0.1:8899;
  }
}

#alias和root的区别

#alias

  • 路径和目录可以不同
# 访问 https://xxxxx.com/11/yy.txt 时,会回源 /etc/nginx/files-dir/22/yy.txt
location /11/ {
  alias /etc/nginx/files-dir/22/;
}

#root

  • 路径和目录要相同
# 访问 https://xxxxx.com/imgs/yy.jpg,会回源 /etc/nginx/images-dir/imgs/yy.jpg
location /imgs/ {
  root /etc/nginx/images-dir/;
}

# 访问 https://xxxxx.com/index.html,会回源 /etc/nginx/html-dir/index.html
location / {
  root /etc/nginx/html-dir;
  index index.html
}

#正则匹配

#location匹配规则

  • =
    :精准匹配
  • /
    :匹配任何请求
  • ^
    :匹配字符串的开始位置
  • $
    :匹配字符串的结束位置
  • ^~
    :前缀匹配,只匹配普通字符,一旦匹配成功,匹配的字符串是最长的,则停止进一步匹配
    # 优先级高于正则匹配
    location ^~ /images/ {
      ...
    }
    
  • ~
    :大小写敏感的正则匹配
  • ~*
    :大小写不敏感的正则匹配
    # 将匹配以 .jpg、.gif 结尾的请求(如:.jpG, .JPG、.GIF)
    location ~* \.(jpg|gif)$ {
      ...
    }
    

#location匹配顺序

  1. =
    :精准匹配
  2. ^~
    :前缀匹配
  3. ~*
    :正则匹配
  4. /
    :匹配任何请求

#server_name

server {
  listen 80;
  server_name "~^(((www|abc)([0-9a-z]{0,5}))\.)?(example)\.(com)$";

  location / {
    ...
  }
}

#反向代理

#反代https文件

proxy_cache_path /home/hard-disk/cache_zone_file levels=1:2 keys_zone=cache_zone_file:500m inactive=30d max_size=2g use_temp_path=off;

server {
  listen 80;
  server_name file.example.com;

  location ~ ^/cust-path-todo/(.*) {
    rewrite ^/cust-path-todo/(.*)(.svg|.html|.apk)(.*) /$1$2 break;

    proxy_set_header Host images.target-todo.com;
    proxy_pass https://images.target-todo.com;

    proxy_cache cache_zone_file;
    proxy_cache_key $request_uri;

    add_header Cache-Status "$upstream_cache_status";
    add_header "Cache-Control" "public, max-age=2592000";

    proxy_cache_valid 200 206 304 30d;
    proxy_cache_valid any 30s;

    proxy_next_upstream error timeout http_502 http_504;
    proxy_next_upstream_timeout 5s;
    proxy_next_upstream_tries 2;

    proxy_ssl_server_name on;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_set_header referer "https://www.target-todo.com/";
    proxy_set_header origin "https://www.target-todo.com";
    proxy_set_header User-Agent "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1";

    # proxy_hide_header xxxxxx-todo;
    # proxy_ignore_headers "Cache-Control" "Expires" "Set-Cookie" "Vary";
  }
}

#重定向

#@ -> www

server {
  listen 80;
  server_name example.com;
  return 301 https://www.example.com$request_uri;
}

#如404重定向

server {
  listen 80;
  server_name example.com;

  location @errorRedirect {
    return 301 https://$host/;
  }

  location / {
    proxy_intercept_errors on;
    error_page 404 = @errorRedirect;

    ...
  }
}

#返回内容

#下载文件

server {
  listen 80;
  server_name file.example.com;

  location ~* \.(txt|apk)$ {
    if ( $args ~ ^filename=(.*) ) {
      add_header Content-Disposition "attachment; filename=$1";
    }
    add_header "Cache-Control" "public, max-age=2592000";
    root /etc/nginx/files-dir;
  }

  ...
}

#返回文本

location / {
  add_header Content-Type "text/html; charset=utf-8";
  return 200 "OK";
}