41

Nginx 基础用途拾遗

 4 years ago
source link: https://soulteary.com/2020/05/20/nginx-basic-use-supplement.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Nginx 是一款大家日常再熟悉不过的软件,稳定高效是这款软件的标签。常见 Nginx 会做为地址转发服务或提供文件托管能力。但是 Nginx 的用法其实不止于此,原生 Nginx 还有许多实用的功能,能够实现一些业务中麻烦的小细节。

本文将介绍三种基础用法,如果你熟悉 Nginx 和容器,阅读时间大概是五分钟。

写在前面

本次使用的示例环境,均使用容器进行模拟。如果你对容器还不是很熟悉,欢迎浏览之前的Docker 相关文章内容。

配合 compose 轻松创建健康检查

一些前端类的容器,本身并没有服务能力,但是为了能够享受容器服务的基础健康检查,以及提供给外部诸如负载均衡等服务使用,我们可能不得不启动一个语言运行时,比如 Node / PHP / Java,不过如果你使用 Nginx 作为前端使用的 Web 服务软件,他本身就自带了基础的路由功能和定制响应码和内容的能量,可以避免我们引入庞大的语言运行时。

我们只需要在配置内添加一个名为 /health 的路由,然后配合 default_typereturn 指令就可以完成我们想要的“当服务健康时,返回HTTP CODE 200,并输出一些内容”。

server {
  listen 80;
 
  location = /health {
    access_log off;
    default_type text/html;
    return 200 'alive';
  }
}

你或许会说,我们可以让健康检查软件检查业务路由,但是我想告诉你的是,当我们把路由独立之后,你会发现健康检查的响应时间更快了,除此之外,我们还可以对日志进行丢弃。如果你将健康检查路由和业务路由放在一起,海量的健康检查日志和业务日志在一起,会让你调试的时候痛不欲生。

配合 compose 进行健康检查也很容易:

version: "3.6"
 
services:
 
  health.test.soulteary.com:
    image: nginx:1.18.0-alpine
    volumes:
      - ./default.conf:/etc/nginx/conf.d/default.conf:ro
    healthcheck:
      # 老版本使用
      # test: ["CMD-SHELL", "wget -q --spider --proxy off localhost:80/health || exit 1"]
      test: ["CMD-SHELL", "curl -f localhost/health || exit 1"]
      interval: 3s
      retries: 12

当你使用 docker ps 查看容器进程的时候,你会看到我们的容器会标记为“healthy”,之后可以配合各种策略进行容器服务基础容灾等基本操作。

CONTAINER ID        IMAGE                           COMMAND                  CREATED             STATUS                    PORTS                                                  NAMES
2afd71cd562e        nginx:1.18.0-alpine             "nginx -g 'daemon of…"   10 minutes ago      Up 3 seconds (healthy)   80/tcp             health.test.soulteary.com_1

使用 Nginx 聚合不同站点内容

日常开发过程中,在遇到“前端跨域”、“短信模版中链接固定”、“既有程序调用来源限制”等场景下,会遇到需要聚合站点域名或路径的情况。

我们知道使用编程语言,可以实现远程内容获取和转写,但是实际上使用 Nginx 的反向代理功能可以更加轻松地做到内容聚合。

比如,在做内容聚合前,我们需要访问的内容在 apple.test.soulteary.combanana.test.soulteary.com ,而我们希望聚合后的内容在 test.soulteary.com 中展示。

为了方便模拟环境,我们先创建一个 compose 配置文件:

version: "3.6"
 
services:
 
  test.soulteary.com:
    image: nginx:1.18.0-alpine
    ports:
      - 8080:8080
    volumes:
      - ./default.conf:/etc/nginx/conf.d/default.conf:ro
 
  apple.test.soulteary.com:
    image: nginx:1.18.0-alpine
    volumes:
      - ./apple.test.soulteary.com.conf:/etc/nginx/conf.d/default.conf:ro
 
  banana.test.soulteary.com:
    image: nginx:1.18.0-alpine
    volumes:
      - ./banana.test.soulteary.com.conf:/etc/nginx/conf.d/default.conf:ro

配置文件中的 services 的三个子项分别代表聚合后的站点,以及两个需要被聚合的站点,可以想象为现实中网络相通的三台服务器。

继续创建 apple.test.soulteary.com.conf 这个 Nginx 配置文件。

server {
    listen 80;
    server_name apple.test.soulteary.com;
    default_type text/html;
 
    location / {
        return 200 'apple.test.soulteary.com';
    }
}

可以看到,站点功能很简单,访问 / 的时候,返回 HTTP CODE 200,并输出文本内容 apple.test.soulteary.com ,同理我们创建另外一个站点的 Nginx 配置文件 banana.test.soulteary.com

最后,创建用于聚合配置文件的 Nginx 配置。

server {
    listen 8080;
    server_name test.soulteary.com;
 
    location = / {
        return 302 /apple;
    }
 
    location /apple {
        proxy_pass http://apple.test.soulteary.com/;
        proxy_set_header Host "apple.test.soulteary.com";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
 
    location /banana {
        proxy_pass http://banana.test.soulteary.com/;
        proxy_set_header Host "banana.test.soulteary.com";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

可以看到配置十分简单,通过 proxy_pass 配合 proxy_set_header 两个指令,我们就将不同站点聚合到了一块。

test.soulteary.com 绑定至本地,然后启动服务,使用命令行访问站点,可以看到配置符合预期。

# curl http://test.soulteary.com:8080/apple  
apple.test.soulteary.com
 
# curl http://test.soulteary.com:8080/banana
banana.test.soulteary.com

转发 Git SSH 这类 TCP 请求

Nginx 除了能够处理 HTTP 请求外,对于 TCP 类型的数据一样能做到聚合/转发。比如这里我们想将生产环境的某台 GitLab 的访问权限限制到具体的 IP,除了使用云平台的防火墙规则外,使用 Nginx 一样可以做到。

这里要使用的是 Nginx 的 ngx_stream_proxy_module 模块。

Nginx 容器默认配置仅包含了 HTTP 服务模式,所以这次修改不能和上面一样,仅修改 “vhost” 配置,需要修改 nginx.conf 主配置,在修改之前,我们先使用脚本看看默认的配置长什么样。

docker run --rm -it nginx:1.18.0-alpine cat /etc/nginx/nginx.conf

执行上面的命令,可以看到默认的配置很简单:

user  nginx;
worker_processes  auto;
 
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
 
 
events {
    worker_connections  1024;
}
 
 
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
 
    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;
 
    keepalive_timeout  65;
 
    #gzip  on;
 
    include /etc/nginx/conf.d/*.conf;
}

为了能够让读者轻松验证,我们假设目标仓库是 GitHub,在对配置文件简单修改后:

user  nginx;
worker_processes  auto;
 
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
 
 
events {
    worker_connections  1024;
}
 
 
stream{
    server{
        listen 2223;
        proxy_pass github.com:22;
        proxy_connect_timeout 10s;
        proxy_timeout 20s;
        proxy_buffer_size 512k;
    }
}

我们继续创建一个 compose 配置文件:

version: "3.6"
 
services:
 
  proxy-git.test.soulteary.com:
    image: nginx:1.18.0-alpine
    ports:
      - 2223:2223
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro

使用 docker-compose up 将服务启动之后,我们使用经典的 Git 测试命令行对服务进行验证:

# ssh -T [email protected] -p 2223
The authenticity of host '[127.0.0.1]:2223 ([127.0.0.1]:2223)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
 
Warning: Permanently added '[127.0.0.1]:2223' (RSA) to the list of known hosts.
 
Hi soulteary! You've successfully authenticated, but GitHub does not provide shell access.

你会发现此刻我们想要的目标已经达到了,不信的话,你可以使用相同命令去测试下原始 Git 服务地址。

# ssh -T [email protected]    
 
Hi soulteary! You've successfully authenticated, but GitHub does not provide shell access.

小节开始前提过,想进行来源限制,可以搭配 Nginx 原生的 allow / deny 指令来完成:

location / {
    deny  192.168.1.1;
    allow 192.168.1.0/24;
    allow 10.1.1.0/16;
    allow 2001:0db8::/32;
    deny  all;
}

最后

Nginx 好玩、实用的用法其实还有不少,时间原因,就不在此展开了。

–EOF


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK