快速掌握 nginx 的核心用法(全栈必备)

docker 里使用 nginx

Nginx 是一款高性能的 Web 服务器,广泛用于静态资源托管和作为动态资源的反向代理。

Docker 是容器化技术,可以在容器中运行各种服务。

docker deskttop 搜索 nginx(需科学上网),点击 run:

输入容器名,将宿主机的 81 端口映射到容器的 80 端口,并启动容器:

浏览器访问下 http://localhost:81 可以看到 nginx 欢迎页面:

托管静态 html 页面

在 Docker 容器中,在 files 面板可以看到容器内的文件,静态文件默认存放在 /usr/share/nginx/html/ 目录下:

双击其中 index.html 看看:

这就是我们之前访问看到的页面。

通过 Docker 的 docker cp 命令,可以在宿主机和容器之间复制文件。

我们先把这个目录复制出来:

bash 复制代码
# 将名为 nginx1 的 Docker 容器中的 /usr/share/nginx/html 目录复制到宿主机的当前用户的主目录下,并命名为 nginx-html
docker cp nginx-test:/usr/share/nginx/html ~/nginx-html

比如我们把这个目录再复制到容器里:

bash 复制代码
docker cp  ~/nginx-html/html nginx-test:/usr/share/nginx/html-test


可以看到容器内就多了 html-test 目录。

我们右键删除下 html 文件:

然后我们在宿主机进去 html-test 目录,添加两个文件,并复制到容器的 html 中:

bash 复制代码
cd nginx-html/html

echo hello test1 > test1.html

echo hello test2 > test2.html

docker cp  ~/nginx-html/html nginx-test:/usr/share/nginx/html


然后浏览器访问下试试:

现在就可以访问容器内的这些目录了。

也就是说只要放到 /usr/share/nginx/html 下的文件,都可以通过被访问到。

这是因为 nginx 的默认配置。

Nginx 配置文件解析

我们看下 nginx 主配置文件,也就是 /etc/nginx/nginx.conf,通常放一些全局配置,比如错误日志的目录等。

复制出来看看:

bash 复制代码
docker cp  nginx1:/etc/nginx/nginx.conf ~/nginx-html

http 部分通过 include 指令引入 /etc/nginx/conf.d/*.conf 的子配置文件,这些文件通常包含具体的路由配置。

我们把这个目录也复制出来看看:

这里面就配置了 localhost:80 的虚拟主机下的所有路由。

虚拟主机就是可以用一台 nginx 服务器来为多个域名和端口的提供服务。

在 conf.d 目录下的配置文件中,可以设置针对特定虚拟主机的路由规则。

location 指令详解

location 指令用于配置路由规则,支持多种匹配语法:

  • location = /uri:精确匹配指定的 URI。
  • location /uri:前缀匹配,匹配以 /uri 开头的任意路径。
  • location ^~ /uri:前缀匹配,但优先级高于正则匹配。
  • location ~ /pattern:正则匹配,区分大小写。
  • location ~* /pattern:正则匹配,不区分大小写。

这些匹配语法的优先级顺序为:精确匹配(=) > 高优先级前缀匹配(^) > 正则匹配 ( 和 ~*)> 前缀匹配(/)。

例如:

nginx 复制代码
server {
    listen 80;
    server_name example.com;

    # 精确匹配 /,通常用于网站首页
    location = / {
        root /var/www/html;
        index index.html index.htm;
    }

    # 普通字符串匹配,匹配任何以 /images 开头的请求
    location /images/ {
        root /var/www/html;
    }

    # 正则匹配,区分大小写,匹配以 .png 结尾的请求
    location ~ \.png$ {
        root /var/www/images;
    }

    # 正则匹配,不区分大小写,匹配以 .jpg 或 .jpeg 结尾的请求
    location ~* \.(jpg|jpeg)$ {
        root /var/www/images;
    }

    # 最长非正则前缀匹配,匹配任何以 /documents 开头的请求
    # 并且不再检查后续的正则 location 块
    location ^~ /documents/ {
        root /var/www/html;
    }

    # 如果以上 location 块都不匹配,则使用这个默认的 location
    location / {
        root /var/www/html;
        index index.html index.htm;
    }
}

root 与 alias 指令

root 和 alias 是 Nginx 配置中用来指定资源路径的两个指令,它们都可以用来定义服务器上文件的位置。

root 指令

root 指令用于设置服务器中请求的根目录。当请求到来时,Nginx 会将请求的 URI 直接附加到 root 指定的路径后面,以此来定位文件:

nginx 复制代码
location /images/ {
    root /data;
}

如果有一个请求是 example.com/images/cat....,Nginx 会在 /data/images/cat.png 的位置寻找文件。

alias 指令

alias 指令用于将请求的 URI 映射到服务器上的一个不同的路径,但它不会像 root 那样直接附加 URI:

nginx 复制代码
location /images/ {
    alias /data/pictures/;
}

如果有一个请求是 example.com/images/cat....,Nginx 会在 /data/pictures/cat.png 的位置寻找文件,注意这里的 URI /images/ 被替换成了 /data/pictures/。

综上所述,如果只是想为整个服务器或者某个特定的 location 设置一个基础路径,那么 root 是一个不错的选择。如果需要将某个 location 映射到一个完全不同的路径,那么 alias 更加合适。

文件访问机制

当客户端请求一个 URL 时,Nginx 根据配置文件中的 location 指令查找相应的文件:

  1. 解析 URL:Nginx 解析客户端请求的 URL。
  2. 匹配路径:根据 location 指令匹配请求路径。
  3. 查找文件:使用 root 指定的目录作为基准目录,将请求路径拼接在 root 指定的目录后,查找相应的文件。

例如,当客户端请求 http://localhost/test1.html 时,Nginx 将:

  1. 解析请求路径 /test1.html。
  2. 匹配 location / 指令。
  3. 使用 root /usr/share/nginx/html 指定的目录,将路径 /test1.html 拼接在后面,查找文件 /usr/share/nginx/html/test1.html。

因此,只要将文件放在 /usr/share/nginx/html 目录下,Nginx 就能根据请求路径正确找到并返回这些文件。

配置示例

以下是一些 location 配置示例,展示了如何返回静态 HTML 文件:

nginx 复制代码
location /222 {
  alias /usr/share/nginx/html;
}

location ~ ^/333/bbb.*\.html$ {
  alias /usr/share/nginx/html/bbb.html;
}

修改配置后,将宿主机上的 Nginx 配置文件 default.conf 复制到名为 nginx1 的 Docker 容器内的 /etc/nginx/conf.d/ 目录下:

nginx 复制代码
docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf

在容器 exec 内输入 nginx -s reload 重新加载配置:

动态资源的反向代理

请求发给 nginx,由它转发给应用服务器,这一层也可以叫做网关。

正向代理与反向代理的区别

  • 正向代理:用户通过代理服务器访问互联网,代理服务器代表用户发出请求,因此称为正向代理。
  • 反向代理:用户请求服务器资源时,由代理服务器代替原始服务器响应请求,对用户来说是透明的,因此称为反向代理。

Nginx 反向代理配置实践

创建 Nest.js 服务

bash 复制代码
npx nest new nest-app -p npm

启动服务:

bash 复制代码
npm run start:dev

当在浏览器访问 http://localhost:3000 出现 "hello world" 时,表示服务启动成功。

Nginx 反向代理配置

首先,在 Nginx 配置文件中添加一个路由规则:

bash 复制代码
location ^~ /api {
    proxy_pass http://192.168.1.6:3000;
}

这条规则将所有以 /api 开头的 URL 请求代理到 http://192.168.1.6:3000。其中,^~ 用于提高匹配优先级。

将修改后的配置文件复制到 Docker 容器中,并重新加载 Nginx 配置:

bash 复制代码
docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf

此时,通过访问 http://localhost:81/api,可以看到 Nest.js 服务返回的响应。

实际路径上是从 Nest -> Nginx -> 浏览器 。

Nginx 反向代理的作用

通过 Nginx 反向代理,我们可以在这一层进行多种操作,例如修改请求、响应信息,修改 HTTP 头部信息。

此外,Nginx 还可以实现负载均衡,通过将请求分配到不同的服务器来提高系统的可用性和扩展性。

Nginx 负载均衡配置

Nginx 通过负载均衡机制,将接收到的请求按照预定规则分配到多个服务器上,以此提高系统的处理能力和可用性。

负载均衡策略

Nginx 支持多种负载均衡策略,包括:

  • 轮询(Round Robin):默认方式,。请求按时间顺序逐一分配到不同的后端服务器。
  • 权重(Weight):基于轮询,但可以设置不同服务器的权重。
  • IP 哈希(IP Hash):根据用户 IP 的哈希结果分配,可以解决会话持久性问题。
  • 最少连接(Least Connections):选择当前连接数最少的服务器。
  • 响应时间(Fair):根据服务器的响应时间来分配请求,需要安装 nginx-upstream-fair 插件。

实现权重和 IP 哈希策略

把之前 nest 服务停掉,在 3001 和 3002 端口 npm run start 各跑一个。

改下 nginx 配置文件,我们可以在 Nginx 配置文件的 upstream 模块中设置服务器实例:

proxy_pass 通过 upstream 的名字来指定。此时是默认轮询的方式。

proxy_set_header 是设置请求头。

指定权重的策略:

我们也可以用 ip_hash 的方式(使用 ip_hash 算法实现会话粘性,即相同的客户端请求会被分发到同一台服务器上)

然后,将配置文件复制到 Docker 容器中,并 nginx -s reload 重新加载 Nginx 配置:

bash 复制代码
docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf

在 nest 中加个路由:

添加一个全局的前缀:

访问 http://localhost:81/api ,看打印日志权重差不多是 1: 2 轮询几率:

command + k 清空控制台,然后请求,可以发现 ip_hash 是一直请求一台服务器:

这就是负载均衡。

相关推荐
下雪天的夏风9 分钟前
TS - tsconfig.json 和 tsconfig.node.json 的关系,如何在TS 中使用 JS 不报错
前端·javascript·typescript
diygwcom20 分钟前
electron-updater实现electron全量版本更新
前端·javascript·electron
wn53125 分钟前
【Go - 类型断言】
服务器·开发语言·后端·golang
Hello-Mr.Wang37 分钟前
vue3中开发引导页的方法
开发语言·前端·javascript
希冀1231 小时前
【操作系统】1.2操作系统的发展与分类
后端
程序员凡尘1 小时前
完美解决 Array 方法 (map/filter/reduce) 不按预期工作 的正确解决方法,亲测有效!!!
前端·javascript·vue.js
GoppViper1 小时前
golang学习笔记29——golang 中如何将 GitHub 最新提交的版本设置为 v1.0.0
笔记·git·后端·学习·golang·github·源代码管理
爱上语文2 小时前
Springboot的三层架构
java·开发语言·spring boot·后端·spring
serve the people2 小时前
springboot 单独新建一个文件实时写数据,当文件大于100M时按照日期时间做文件名进行归档
java·spring boot·后端
编程零零七4 小时前
Python数据分析工具(三):pymssql的用法
开发语言·前端·数据库·python·oracle·数据分析·pymssql