nginx个人理解

nginx 个人理解

服务日志都要配上哈

这份文档主要就是看例子,理解几种最常见的 nginx 写法。

1. 静态网站怎么写

例子

直接用端口访问

server {
listen 8123;
listen [::]:8123;

access_log /var/log/nginx/hexo_8123_access.log;
error_log /var/log/nginx/hexo_8123_error.log warn;

root /data/hexo;
index index.html;


location / {
try_files $uri $uri/ /index.html;
}
}

说明

这段配置表示:

  • nginx 监听 8123
  • 网站目录是 /data/hexo
  • 找不到文件时回退到 /index.html

适合:

  • Hexo
  • Vue
  • React
  • 单页应用

如果:

  • nginx 已启动
  • 端口 8123 已放行
  • /data/hexo/index.html 存在

那就可以直接通过:

服务器IP:8123

访问。

如果你是普通静态网站,不需要回退到首页,也可以写成:

location / {
try_files $uri $uri/ =404;
}

静态网站走域名

HTTP

server {
listen 80;
listen [::]:80;
server_name blog.example.com;

access_log /var/log/nginx/blog_http_access.log;
error_log /var/log/nginx/blog_http_error.log warn;

root /data/hexo;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}
}

这表示:

  • 域名 blog.example.com 访问这个站点
  • 走的是 HTTP
  • 不需要 SSL 证书

访问方式:

http://blog.example.com

HTTPS

server {
listen 80;
listen [::]:80;
server_name blog.example.com;

return 301 https://$host$request_uri;
}

server {
listen 443 ssl;
listen [::]:443 ssl;
server_name blog.example.com;

access_log /var/log/nginx/blog_https_access.log;
error_log /var/log/nginx/blog_https_error.log warn;

ssl_certificate /etc/nginx/ssl/blog.example.com.crt;
ssl_certificate_key /etc/nginx/ssl/blog.example.com.key;

root /data/hexo;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}
}

这表示:

  • 80 负责跳转到 HTTPS
  • 443 正式提供静态网站
  • 这里必须配置 SSL 证书

访问方式:

https://blog.example.com

屏蔽直接 IP 访问

就在正式域名站点的基础上,再额外补一个默认兜底站点。

HTTP 场景

server {
listen 80;
listen [::]:80;
server_name blog.example.com;



root /data/hexo;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}
}

server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
access_log /var/log/nginx/default_http_drop_access.log;
error_log /var/log/nginx/default_http_drop_error.log warn;
return 444;
}

HTTPS 场景

server {
listen 80;
listen [::]:80;
server_name blog.example.com;
access_log /var/log/nginx/blog_http_redirect_access.log;
error_log /var/log/nginx/blog_http_redirect_error.log warn;
return 301 https://$host$request_uri;
}

server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
access_log /var/log/nginx/default_http_drop_access.log;
error_log /var/log/nginx/default_http_drop_error.log warn;
return 444;
}

server {
listen 443 ssl;
listen [::]:443 ssl;
server_name blog.example.com;

access_log /var/log/nginx/blog_https_access.log;
error_log /var/log/nginx/blog_https_error.log warn;

ssl_certificate /etc/nginx/ssl/blog.example.com.crt;
ssl_certificate_key /etc/nginx/ssl/blog.example.com.key;

root /data/hexo;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}
}

server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name _;

access_log /var/log/nginx/default_https_drop_access.log;
error_log /var/log/nginx/default_https_drop_error.log warn;

ssl_certificate /etc/nginx/ssl/blog.example.com.crt;
ssl_certificate_key /etc/nginx/ssl/blog.example.com.key;

return 444;
}

这表示:

  • 正式域名访问正常返回
  • 直接访问 IP 或错误 Host 的请求直接丢掉

2. 反向代理怎么写

例子

server {
listen 80;
listen [::]:80;
server_name api.example.com;

access_log /var/log/nginx/api_http_access.log;
error_log /var/log/nginx/api_http_error.log warn;

location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

说明

这表示:

  • 用户访问 api.example.com
  • 请求先到 nginx
  • nginx 再把请求转发给本机 127.0.0.1:8000

适合:

  • FastAPI
  • Flask
  • Django
  • Node
  • Java 服务

也就是说:

  • 对外入口是 nginx
  • 真正处理业务的是本地服务端口

如果想屏蔽直接 IP 访问

就在反向代理站点基础上,再额外补默认兜底站点。

server {
listen 80;
listen [::]:80;
server_name api.example.com;

access_log /var/log/nginx/api_http_access.log;
error_log /var/log/nginx/api_http_error.log warn;

location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
access_log /var/log/nginx/default_http_drop_access.log;
error_log /var/log/nginx/default_http_drop_error.log warn;
return 444;
}

3. HTTPS + 反向代理怎么写

例子

server {
listen 80;
listen [::]:80;
server_name api.example.com;
access_log /var/log/nginx/api_http_redirect_access.log;
error_log /var/log/nginx/api_http_redirect_error.log warn;
return 301 https://$host$request_uri;
}

server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
access_log /var/log/nginx/default_http_drop_access.log;
error_log /var/log/nginx/default_http_drop_error.log warn;
return 444;
}

server {
listen 443 ssl;
listen [::]:443 ssl;
server_name api.example.com;

access_log /var/log/nginx/api_https_access.log;
error_log /var/log/nginx/api_https_error.log warn;

ssl_certificate /etc/nginx/ssl/api.example.com.crt;
ssl_certificate_key /etc/nginx/ssl/api.example.com.key;

location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name _;

access_log /var/log/nginx/default_https_drop_access.log;
error_log /var/log/nginx/default_https_drop_error.log warn;

ssl_certificate /etc/nginx/ssl/api.example.com.crt;
ssl_certificate_key /etc/nginx/ssl/api.example.com.key;

return 444;
}

说明

这表示:

  • 80 正式域名跳转到 HTTPS
  • 80 default_server 丢弃其他访问
  • 443 正式域名做反向代理
  • 443 default_server 丢弃其他访问

所以外部用户实际访问的是:

https://api.example.com

而不是:

IP:8000

4. 负载均衡怎么写

例子

upstream api_backend {
server 127.0.0.1:8001;
server 127.0.0.1:8002;
}

server {
listen 80;
listen [::]:80;
server_name api.example.com;

access_log /var/log/nginx/api_lb_access.log;
error_log /var/log/nginx/api_lb_error.log warn;

location / {
proxy_pass http://api_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

说明

这表示:

  • 后端不是一台服务,而是两台
  • nginx 先定义一个 upstream
  • 然后把请求交给这个服务组

常见理解就是:

  • 一台机器压力大了
  • 就让多台后端一起处理请求

如果想带 HTTPS,也是在这个基础上继续套上前面的 80 -> 443443 ssl 写法。

5. 同一个域名按路径分发到不同服务怎么写

例子

例如你想要:

  • web.dostorm.com/v1 访问 127.0.0.1:8001
  • web.dostorm.com/v2 访问 127.0.0.1:8002

可以这样写:

server {
listen 80;
listen [::]:80;
server_name web.dostorm.com;

access_log /var/log/nginx/web_router_access.log;
error_log /var/log/nginx/web_router_error.log warn;

location /v1/ {
proxy_pass http://127.0.0.1:8001/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /v2/ {
proxy_pass http://127.0.0.1:8002/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

说明

这表示:

  • web.dostorm.com/v1/... 转发到 127.0.0.1:8001/...
  • web.dostorm.com/v2/... 转发到 127.0.0.1:8002/...

这里最后那个 / 要注意:

proxy_pass http://127.0.0.1:8001/;

这种写法通常表示:

  • /v1/ 这个前缀替换掉
  • 再把剩余路径转给后端

例如:

  • 用户访问:
    web.dostorm.com/v1/users
  • 后端 8001 实际收到的通常是:
    /users

如果你希望后端保留 /v1/ 这个前缀,那常见写法就是不要在 proxy_pass 后面加最后这个 /

location /v1/ {
proxy_pass http://127.0.0.1:8001;
}

这时后端更可能收到:

  • /v1/users

6. 一个子域名对应一个服务怎么写

例子

这也是很常见的一种写法,只不过它不是按路径分发,而是按子域名分发。

例如你有多个本地服务:

  • 博客前端:127.0.0.1:8123
  • API 服务:127.0.0.1:8000
  • 管理后台:127.0.0.1:9000

然后你想分别对外提供:

  • blog.example.com
  • api.example.com
  • admin.example.com

那就可以这样写:

server {
listen 80;
listen [::]:80;
server_name blog.example.com;

access_log /var/log/nginx/blog_subdomain_access.log;
error_log /var/log/nginx/blog_subdomain_error.log warn;

location / {
proxy_pass http://127.0.0.1:8123;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

server {
listen 80;
listen [::]:80;
server_name api.example.com;

access_log /var/log/nginx/api_subdomain_access.log;
error_log /var/log/nginx/api_subdomain_error.log warn;

location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

server {
listen 80;
listen [::]:80;
server_name admin.example.com;

access_log /var/log/nginx/admin_subdomain_access.log;
error_log /var/log/nginx/admin_subdomain_error.log warn;

location / {
proxy_pass http://127.0.0.1:9000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

说明

这表示:

  • 一个子域名对应一个本地服务
  • 所有请求先到 nginx
  • nginx 再按 server_name 分别转发到不同端口

这种方式特别适合:

  • 博客
  • 接口服务
  • 管理后台
  • 不同系统之间想彻底隔离入口

也就是说,子域名本身就是服务入口。

如果后面都要上 HTTPS,也是在这个基础上,分别给每个子域名继续加:

  • 80 -> 443 跳转
  • 443 ssl
  • 对应证书