Code前端首页关于Code前端联系我们

结合Docker,你将了解到Nginx的核心用法:反向代理+负载均衡

terry 2年前 (2023-09-28) 阅读数 73 #未命名

Nginx是一个流行的服务器。一般用于托管静态资源,反向代理动态资源。

Docker 是一种流行的容器技术,可以运行任何服务。

如何结合使用Docker + Nginx?

我们来试试:

首先下载 Docker,直接安装 Docker Desktop: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

它是用来管理容器和镜像的: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

安装完成后,就可以使用 docker 命令了: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

然后运行nginx 图像。

搜索nginx(这一步需要科学上网,需要访问网站http://hub.docker.com),点击运行:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

输入要映射的容器名称和端口:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

这里将主机的81端口映射到容器中的80端口,点击运行。

此时可以看到docker容器正在运行,并且正在打印日志文件: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

用浏览器访问http://localhost:81,可以看到nginx欢迎页面: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

这个当然是在容器中运行服务了。 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

但当前页面是默认页面。我想使用 nginx 来托管一些静态 html 页面。我应该怎么办?

首先我们需要知道当前的配置文件和页面位于哪里。

在文件面板中可以看到容器内的文件: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

/usr/share/nginx/html/文件夹下都是静态文件。

双击打开index.html看看:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

和我们在浏览器中看到的页面一模一样。

也就是说,这个文件夹就是存放静态文件的文件夹。

我们可以把自己的html放在这个文件夹里吗?

我们先复制这个文件夹:

docker cp  nginx1:/usr/share/nginx/html ~/nginx-html
结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

docker cp 该命令用于在主机和容器之间复制文件和文件夹。 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

比如我们把这个文件夹复制到容器中:

docker cp  ~/nginx-html nginx1:/usr/share/nginx/html-xxx

可以看到容器里有这个文件夹:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

然后我们在这个文件夹中添加两个html文件来试试:

echo aaa > aaa.html

echo bbb > bbb.html

docker cp  ~/nginx-html nginx1:/usr/share/nginx/html
结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

但是当目标文件夹存在时,docker会将其复制到目标文件夹: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

我们需要先从容器中删除该文件夹,然后复制它: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

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

这样就可以了: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

然后尝试使用浏览器访问它:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

现在您可以访问容器中的这些文件夹。

即只要放在/usr/share/nginx/html下的文件是可以访问的。

但是为什么呢?

这是由于nginx默认配置造成的。

我们看一下nginx的配置文件,它是/etc/nginx/nginx.conf。 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

复制下来查看一下:

docker cp  nginx1:/etc/nginx/nginx.conf ~/nginx-html

这是nginx的默认配置:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

其实这个nginx.conf叫做主配置文件,里面一般包含一些全局配置比如错误日志目录、

可以看到http下有一个include,引入了/etc/nginx/conf.d/*.conf的配置。

一般来说,具体的路由配置都在这些子配置文件中。

目录conf.d表示配置目录。

我们复制这个文件夹看看:

docker cp  nginx1:/etc/nginx/conf.d ~/nginx-html

localhost:80虚拟主机下的所有路由都配置在这里。 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

什么是虚拟主机?

可以使用一台nginx服务器为多个域名和端口提供服务。

只需添加一些服务器配置即可。

这里我们配置localhost:80虚拟主机。

下面的位置是路由配置。

例如这个配置: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

它配置/下的所有路由,并将它们定位在root指定的目录中。

所以从/usr/share/nginx/html/aaa.html找到http://localhost/aaa.html。

位置支持不同的语法。让我们逐一尝试:

location = /111/ {
    default_type text/plain;
    return 200 "111 success";
}

location /222 {
    default_type text/plain;
    return 200 $uri;
}

location ~ ^/333/bbb.*\.html$ {
    default_type text/plain;
    return 200 $uri;
}

location ~* ^/444/AAA.*\.html$ {
    default_type text/plain;
    return 200 $uri;
}

删除之前的位置/并添加这些路由配置。

这些配置的具体含义稍后讨论。

将此文件复制到容器中:

docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf

然后在容器中的终端中,运行:

nginx -s reload

重新加载配置文件。 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

然后看第一条路由:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

在位置和路径之间添加=,代表精确匹配,即只有完全相同的URL才匹配此路由。 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

不带=表示根据前缀匹配,前缀后面可以跟任意路径。这里的结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

$uri是走当前路径。 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

如果你想支持正则表达式,可以使用~。结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

这里的常规语法并不难理解,以/333/bbb开头,然后中间有字符,最后url以.html结尾。 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

但区分大小写。例如,这不起作用:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

更改为小写:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

如果您希望正则表达式不区分大小写,您可以添加*结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

并尝试:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

所有大写或小写字母都是可以接受。

另外,还有一种语法:

将此配置添加到配置文件中:

location /444 {
    default_type text/plain;
    return 200 'xxxx';
}

然后复制到容器中并重新加载:

docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

目前有两条 /444 路由: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

At此时,浏览器访问还是和上面的路由一样: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

如果想提高优先级,可以使用^~

,改成这样:

location ^~ /444 {
    default_type text/plain;
    return 200 'xxxx';
}

然后复制到容器中重新加载一下:

docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

这个 当找到相同的 URL 时,会找到以下路由: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

也就是说:^~ 可以提高前缀匹配的优先级。

综上所述,一共有 4 种位置语法:

location = /aaa 是与 /aaa 完全匹配的路由。

location /bbb 是前缀与 /bbb 匹配的路由。

location ~ /ccc.*.html 是常规匹配。可以添加 * 表示位置不区分大小写 ~* /ccc.*.html

location ^~ /ddd 是前缀匹配,但优先级更高。

这四种语法的优先级如下:

精确匹配(=)>高优先级前缀匹配(^~)>普通匹配(~~*)>普通前缀匹配

我们现在的内容直接用return返回实际上应该返回一个html文件。

可以改成如下:

location /222 {
    alias /usr/share/nginx/html;
}

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

然后复制到容器中,重新加载:

docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

可以正确返回对应的html: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡结合 Docker学会 Nginx 核心用法:反向代理+负载均衡结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

我之前用过root: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

root 和 root 有什么区别别名? ?例如

以下两个配置:

location /222 {
    alias /dddd;
}

location /222 {
    root /dddd;
}

也是/222/xxx/yyy.html。如果使用根配置,则整个uri在后面被分割为路径。

即会搜索文件/dddd/222/xxx/yyy.html。

如果是别名配置,去掉/222后会分割部分路径。

即查找文件/dddd/xxx/yyy.html。

也就是我们的root和alias的区别在于分割路径时是否包含满足条件的路径。

这是nginx的第一个特性:静态文件托管。

主配置文件位于/etc/nginx/nginx.conf,子配置文件位于/etc/nginx/conf.d目录。

默认的 HTML 路径是 /usr/share/nginx/html。

接下来我们看一下nginx的第二大特性:动态资源的反向代理。

什么是前进,什么是落后?

从用户的角度来看,方向一致的为正向,相反的方向为反向。

例如,有两个这样的代理:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

第一个是正向代理,第二个是反向代理。

第一个代理是代理用户请求,它与用户请求运行方向相同,称为正向代理。

第二个代理是与用户请求相反方向处理用户请求的代理服务器。这称为反向代理。

在测试 nginx 作为反向代理服务器之前,我们先创建一个嵌套服务。

npx nest new nest-app -p npm
结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

运行服务:

npm run start:dev
结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

使用浏览器访问http://localhost:3000。如果看到 hello world,则说明 Nest 服务运行成功: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

添加全局前缀 /api结合 Docker学会 Nginx 核心用法:反向代理+负载均衡结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

更改为 nginx 配置并添加路由:

location ^~ /api {
    proxy_pass http://192.168.1.6:3000;
}

此路由匹配以 /api 开头的 URL,基于前缀。 ^~ 用于提高优先级。

然后将其复制到容器中并重新加载:

docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

然后访问 http://localhost:81/api 可以看到 Nest 服务返回的响应: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

即是这样的: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

为什么我们需要更多的 nginx 代理?

当然在这个级别你可以做很多事情。

例如,更改标头:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

然后将其复制到容器并重新加载:

docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

将标头注入嵌套服务处理程序,打印它:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

,然后使用浏览器打开它。

如果直接访问 Nest 服务,则没有这样的 header: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

访问 nginx 反向代理服务器并进行传输: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

这就是反向代理服务器的作用,可以透明修改请求和回应。

而且,你还可以用它来实现负载均衡。

打印控制器中的访问日志:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

停止nest服务并重新启动npm run restart结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

对3001和3002各执行一个端口:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

浏览器打开后一切正常:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

console还打印了访问日志:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

问题来了。现在有一台 nginx 服务器和两台 Nest 服务器。 nginx应该如何响应? 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

nginx的解决方案是负载均衡,将请求按照一定的规则分配到不同的服务器上。

更改nginx配置文件: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

配置代理上游的目标服务器的所有实例。

下面,proxy_pass 指定为名称upstream。

然后复制到容器并重新加载:

docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

现在我正在访问 http://localhost:81/api 并刷新页面 5 次: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

您可以看到两个嵌套服务,一个 3 次, 1次2次。第二次评价。 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

因为默认是轮询。

共有四种任务分配策略:

  • 轮询:默认方式。
  • 权重:根据民意调查添加权重,即民意调查的概率不同。
  • ip_hash:根据IP的哈希分布,保证每个访问者的请求都固定访问某个服务器,解决会话问题。
  • 公平:根据响应时间分配。这需要安装 nginx-upstream-fair 插件。

我们来测试一下weight和ip_hash方法。

添加一个weight=2,默认为1,所以被两台服务器轮询的几率是2比1。 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

然后复制到容器中并重新加载:

docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

按command + k嵌套服务控制台日志: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

然后我访问了http://localhost:81/api 8次

看打印的日志,民意调查的概率几乎是2:1。 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

这是一项加权民意调查。

我们再尝试一下ip_hash方法; 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

然后复制到容器中并重新加载:

docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

按 command + k 清除 Nest 服务控制台日志: 结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

重新访问 http:// /localhost:81/api

可以看到请求已发送到服务器:结合 Docker学会 Nginx 核心用法:反向代理+负载均衡

这是Nginx的负载均衡策略。

总结

我们通过docker运行nginx服务器,并使用静态资源托管功能和动态资源的反向代理功能。

nginx 配置文件位于 /etc/nginx/nginx.conf 中,默认情况下还会引入 /etc/nginx/conf.d 下的子配置文件。

HTML 默认放置在 /usr/share/nginx/html 下。

我们可以使用docker cp将容器中的文件复制到主机上进行修改。

更改nginx配置,在服务器上配置路由,根据不同的URL返回不同的静态文件。

有 4 种位置语法:

  • location /aaa 匹配
  • location by prefix ^~ /aaa 匹配前缀,优先级更高
  • location = /aaa 精确匹配
  • location ~ /aaa / .*html 正则匹配
  • 位置 ~* /aaa/.*html 正则匹配且不区分大小写

优先级为精确匹配 (=) > 高优先级前缀 (^~) > 正则匹配 (~ ~*) > 常规前缀匹配

除了静态源托管之外,nginx 还可以对动态源进行反向代理。

即请求发送到nginx,nginx转发到应用服务器。该层也可以称为网关。

nginx反向代理可以更改请求和响应信息,例如设置标头。

如果有多个应用服务器,可以在上游配置负载均衡。有四种策略:轮询、加权轮询、ip_hash 和公平。

一旦掌握了静态资源托管和动态资源反向代理+负载均衡,你就掌握了Nginx的核心用法。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门