从零手写实现 nginx-30-upstream+proxy_pass 反向代理指令介绍

前言

大家好,我是老马。很高兴遇到你。

我们为 java 开发者实现了 java 版本的 nginx

https://github.com/houbb/nginx4j

如果你想知道 servlet 如何处理的,可以参考我的另一个项目:

手写从零实现简易版 tomcat minicat

手写 nginx 系列

如果你对 nginx 原理感兴趣,可以阅读:

从零手写实现 nginx-01-为什么不能有 java 版本的 nginx?

从零手写实现 nginx-02-nginx 的核心能力

从零手写实现 nginx-03-nginx 基于 Netty 实现

从零手写实现 nginx-04-基于 netty http 出入参优化处理

从零手写实现 nginx-05-MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)

从零手写实现 nginx-06-文件夹自动索引

从零手写实现 nginx-07-大文件下载

从零手写实现 nginx-08-范围查询

从零手写实现 nginx-09-文件压缩

从零手写实现 nginx-10-sendfile 零拷贝

从零手写实现 nginx-11-file+range 合并

从零手写实现 nginx-12-keep-alive 连接复用

从零手写实现 nginx-13-nginx.conf 配置文件介绍

从零手写实现 nginx-14-nginx.conf 和 hocon 格式有关系吗?

从零手写实现 nginx-15-nginx.conf 如何通过 java 解析处理?

从零手写实现 nginx-16-nginx 支持配置多个 server

从零手写实现 nginx-17-nginx 默认配置优化

从零手写实现 nginx-18-nginx 请求头+响应头操作

从零手写实现 nginx-19-nginx cors

从零手写实现 nginx-20-nginx 占位符 placeholder

从零手写实现 nginx-21-nginx modules 模块信息概览

从零手写实现 nginx-22-nginx modules 分模块加载优化

从零手写实现 nginx-23-nginx cookie 的操作处理

从零手写实现 nginx-24-nginx IF 指令

从零手写实现 nginx-25-nginx map 指令

从零手写实现 nginx-26-nginx rewrite 指令

从零手写实现 nginx-27-nginx return 指令

从零手写实现 nginx-28-nginx error_pages 指令

从零手写实现 nginx-29-nginx try_files 指令

从零手写实现 nginx-30-nginx proxy_pass upstream 指令

从零手写实现 nginx-31-nginx load-balance 负载均衡

nginx 的 upstream+proxy_pass 指令有什么用?

Nginx 的 upstreamproxy_pass 指令主要用于反向代理和负载均衡。

我们可以用一个简单的例子来说明它们的作用。

场景

假设你有一个网站,用户访问的是 www.example.com,但你的服务器有三台机器来处理请求,这三台机器的 IP 分别是 192.168.0.1192.168.0.2192.168.0.3

你希望 Nginx 能够根据负载情况,将用户的请求均匀地分发到这三台机器上。

配置文件示例

以下是一个 Nginx 配置文件的简化示例,展示了如何使用 upstreamproxy_pass 指令:

http {upstream my_backend {server 192.168.0.1;server 192.168.0.2;server 192.168.0.3;}server {listen 80;server_name www.example.com;location / {proxy_pass http://my_backend;}}
}

解读配置

  1. 定义后端服务器组(upstream)

    upstream my_backend {server 192.168.0.1;server 192.168.0.2;server 192.168.0.3;
    }

    在这个部分,我们定义了一个名为 my_backend 的服务器组,包含三台服务器。这就是 upstream 指令的作用:定义一组可以负载均衡的后端服务器。

  2. 配置代理请求(proxy_pass)

    server {listen 80;server_name www.example.com;location / {proxy_pass http://my_backend;}
    }

    在这个部分,我们配置了一个监听在 80 端口的服务器,并指定当用户访问 www.example.com 时,Nginx 会将请求代理到 my_backend 定义的服务器组中。proxy_pass http://my_backend; 这条指令告诉 Nginx,将匹配到的请求(这里是所有路径 /)转发到 my_backend

简单总结

  • upstream:用来定义一组后端服务器,这些服务器会被 Nginx 用于负载均衡。
  • proxy_pass:用来指定请求的目标地址,可以是单个服务器,也可以是一个 upstream 组。

通过这样的配置,Nginx 就可以将用户的请求分发到不同的后端服务器上,实现负载均衡。

这种配置方式灵活且易于管理,让你可以根据需要轻松扩展或修改服务器组的配置。

nginx 为什么选择 upstream+proxy_pass 这两个名字?

Nginx 选择 upstreamproxy_pass 这两个名字,是为了形象地描述它们在请求处理过程中的角色。

让我们用一个通俗易懂的方式来解释它们的名字选择。

Upstream

“Upstream” 的意思是“上游”。想象你正在组织一个农产品的分销网络。

  • 上游:就是农民和农场,他们是最初生产产品的人。
  • 下游:就是超市或市场,他们是最终销售产品给消费者的地方。

在 Nginx 的世界里,“上游”服务器就是那些实际处理和响应请求的后端服务器。

所以,“upstream”这个名字表示这些服务器在请求处理链条中是“上游”的部分,它们是数据和响应的源头。

Proxy Pass

“Proxy” 就是代理。想象你是一个物流公司,负责把农产品从农场运到市场。

  • 代理(proxy):你作为中介,负责把产品从农场转运到市场。
  • 传递(pass):你把农产品从农场运到市场。

在 Nginx 中,“proxy_pass”指令就是告诉 Nginx 要把请求传递给谁,就像你告诉物流公司要把货物送到哪个市场一样。

“proxy_pass”表示“代理传递”的意思,它明确了 Nginx 需要将客户端的请求传递到哪个上游服务器。

为什么是 proxy_pass http://my_backend; 而不干脆是 proxy_pass my_backend;?

Nginx 的 proxy_pass 需要指定协议和地址,以确保配置的明确性和灵活性。下面是对这个问题的详细解释。

为什么需要指定协议?

  1. 明确协议类型http://my_backend 指明了请求应该使用 HTTP 协议进行代理。如果省略协议,如 proxy_pass my_backend;,Nginx 就不知道应该使用 HTTP 还是 HTTPS,或者其他可能的协议。

  2. 一致性和兼容性:Nginx 的 proxy_pass 支持多种协议,比如 HTTP、HTTPS、FastCGI 等。通过显式指定协议,配置文件的可读性和可维护性更好,避免混淆和潜在的配置错误。

如何判断是 upstream 组还是具体 URL?

Nginx 通过以下规则来判断 proxy_pass 是指向 upstream 组还是具体的 URL:

1) 如果 proxy_pass 后面包含协议(如 http://https://),且不在 upstream 组中Nginx 会将其视为具体的 URL。

2) 否则以 http:// or https:// 开头,则认为是 URL

配置示例

假设有以下配置:

http {upstream my_backend {server 192.168.0.1;server 192.168.0.2;}server {listen 80;server_name www.example.com;location / {proxy_pass http://my_backend;}location /specific {proxy_pass http://192.168.0.3;}location /another {proxy_pass my_backend;  # 这种写法会出错}}
}

解释

  • proxy_pass http://my_backend;:明确地告诉 Nginx 使用 HTTP 协议,将请求代理到名为 my_backendupstream 组。
  • proxy_pass http://192.168.0.3;:明确地告诉 Nginx 使用 HTTP 协议,将请求代理到具体的 URL 192.168.0.3
  • proxy_pass my_backend;:这种写法是错误的,因为省略了协议,Nginx 不知道如何处理这个指令。

灵活性和明确性

这种设计保证了配置的灵活性和明确性:

  • 通过显式指定协议,避免了误解和错误配置。
  • 保证了配置文件的清晰度,便于管理和维护。

如何判断是否为 upstream 组?

问题

如果有一个 proxy_pass xxx,又改如何判断到底是到 upstream 组,还是具体的 url 呢?

实现

具体的 java 实现:

import java.util.Set;public class ProxyResolver {public static void main(String[] args) {Set<String> upstream = Set.of("upstream1", "upstream2", "upstream3");String proxy = "http://upstream1"; // 示例输入String result = resolveProxy(proxy, upstream);System.out.println("Resolved to: " + result);}public static String resolveProxy(String proxy, Set<String> upstream) {// 先检查是否是具体的 URLif (proxy.startsWith("http://") || proxy.startsWith("https://")) {// 如果是具体的 URL,判断是否在 upstream 中String potentialUpstream = proxy.substring(proxy.indexOf("//") + 2);if (upstream.contains(potentialUpstream)) {return "Upstream: " + potentialUpstream;} else {return "URL: " + proxy;}} else if (upstream.contains(proxy)) {// 如果不是具体的 URL,直接判断是否在 upstream 中return "Upstream: " + proxy;} else {// 默认情况,无法判断的情况return "Unknown: " + proxy;}}
}

小结

Nginx 的 upstreamproxy_pass 指令用于实现反向代理和负载均衡,简单总结如下:

  1. Upstream:定义了一组后端服务器,每个服务器可以处理请求。这些服务器可以是物理服务器的地址或者其他可访问的网络位置。Upstream 为 Nginx 提供了一个管理和分发请求的目标列表。

  2. Proxy Pass:指示 Nginx 将客户端的请求代理到指定的后端服务器组(upstream)或者具体的服务器地址。它告诉 Nginx 如何转发请求,并且可以指定不同的路径和条件来匹配不同的后端处理逻辑。

通过这两个指令,Nginx 可以实现高效的负载均衡和反向代理,从而提升网站或应用程序的性能、可靠性和扩展性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/47177.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LLM基础模型系列:Prompt-Tuning

------->更多内容&#xff0c;请移步“鲁班秘笈”&#xff01;&#xff01;<------ 大型预训练语言模型的规模不断扩大&#xff0c;在许多自然语言处理 &#xff08;NLP&#xff09; 基准测试中取得了最先进的结果。自GPT和BERT开发以来&#xff0c;标准做法一直是在下游…

SCP 使用教程

SCP&#xff08;Secure Copy Protocol&#xff09;是一种通过加密的方式在本地主机和远程主机之间安全地传输文件的协议。它是基于SSH协议的扩展&#xff0c;允许用户在不同主机之间进行文件复制和传输&#xff0c;是Linux和Unix系统中常用的工具之一。本教程将详细介绍SCP的基…

migrate table com.finebi.persist.impl.entity.PackageSubItemEntity failed

记录一个报错解决过程&#xff0c;finebi在连接外部mysql时&#xff0c;要把finebi里的表导入到mysql&#xff0c;但是如果mysql库不是utf8就会报错如下migrate table com.finebi.persist.impl.entity.PackageSubItemEntity failed 解决方法&#xff1a;用下面语句创建的库是…

数字化教育资源如何适应人工智能时代

01 教育资源应动态适应一线教学需求 用好数字化教育资源是一项系统工程&#xff0c;涉及教育教学的各个方面&#xff0c;包括教师和学生的教育观念与技术观念、信息技术素养&#xff0c;以及课程教学改革、教师培训等。还涉及数字化教育资源提供方的服务&#xff0c;如技术支持…

【STM32嵌入式系统设计与开发---拓展】——1_9_1上拉输入和下拉输入

在使用GPIO引脚时&#xff0c;上拉输入和下拉输入的选择取决于外部电路的特性和应用需求。以下是它们各自的应用场景&#xff1a; 1、上拉输入&#xff08;Pull-up Input&#xff09; 用途: 当默认状态需要为高电平时。 避免引脚悬空&#xff08;floating&#xff09;导致的…

计算机网络——网络层(路由选择协议、路由器工作原理、IP多播、虚拟专用网和网络地址转换)

目录 路由选择协议 因特网的路由选择协议特点 路由信息协议RIP RIP衡量目的网络距离 RIP选择路由器的方式 RIP具有以下三个重要特点 RIP的基本工作流程 RIP的距离向量算法 ​编辑 ​编辑 RIP存在的问题——“坏消息传播得慢” RIP的封装 开放最短路径优先协议OSPF…

在CSS中,使用Flexbox布局时,可以通过几个属性来控制容器内的项目之间的间距

display弹性布局&#xff0c;flex:1是占据剩下的空间 关于displa:flex /* 水平和垂直居中&#xff0c;水平和垂直方向上的间距均匀分布 / .container { display: flex; justify-content: space-between; / 左右对齐 / align-items: center; / 上下间距 */ flex-direction: ro…

YOLOv7 更换Neck之 BiFPN

简介 YOLOv7 是 Ultralytics 公司于 2022 年 4 月发布的最新一代目标检测模型&#xff0c;在 COCO 数据集上取得了56.2 mAP 的惊人成绩&#xff0c;超越了所有已知的目标检测模型。YOLOv7 的核心架构与之前的版本基本一致&#xff0c;但对一些关键模块进行了改进&#xff0c;其…

AcWing 668. 游戏时间2

读取四个整数 A,B,C,D&#x1d434;,&#x1d435;,&#x1d436;,&#x1d437;&#xff0c;用来表示游戏的开始时间和结束时间。 其中 A&#x1d434; 和 B&#x1d435; 为开始时刻的小时和分钟数&#xff0c;C&#x1d436; 和 D&#x1d437; 为结束时刻的小时和分钟数。…

昇思25天学习打卡营第23天|基于MindSpore的Pix2Pix实现图像转换

Pix2Pix实现图像转换 Pix2Pix概述 Pix2Pix是基于条件生成对抗网络&#xff08;cGAN, Condition Generative Adversarial Networks &#xff09;实现的一种深度学习图像转换模型&#xff0c;该模型是由Phillip Isola等作者在2017年CVPR上提出的&#xff0c;可以实现语义/标签到…

Spring Boot app: Failed to determine a suitable driver class

目录 问题描述解决方案 问题描述 我尝试连接springboot&#xff1b;当我运行时&#xff0c;出现错误“Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured."” application.yml 应用程序.yml dat…

【贪心算法】贪心算法30题

一、贪心算法简介 证明贪心策略正确性的常用方法&#xff1a;直接证明、交换论证法、反证法、分类讨论… 二、相关编程题 2.1 柠檬水找零 题目链接 860. 柠檬水找零 - 力扣&#xff08;LeetCode&#xff09; 题目描述 算法原理 提示&#xff1a;最优解和贪心解唯一可能不同…

创建React项目:使用 create-react-app 创建 React 应用

在本文中&#xff0c;我们将介绍如何使用 create-react-app 创建一个名为 react-basic 的 React 应用。以下步骤将帮助你快速搭建一个新的 React 项目。 1. 确保已安装 Node.js 和 npm 在开始之前&#xff0c;确保你的系统上已经安装了 Node.js 和 npm&#xff08;Node 包管理…

提取文本中所有图片的链接地址

从给定的文本中使用正则表达式提取出所有的图片链接地址 代码 import re s这是一段干扰信息这是一段干扰信息这是一段干扰信息这是一段干扰信息这是一段干扰信息这是一段干扰信息https://img1.baidu.com/it/u272155668.1962281314&fm26&fmtauto这是一段干扰信息这是一…

Mongodb 3.6 数据恢复操作

一、安装MongoDB 忽略 二、创建账号和授权 在新的MongoDB上创建用户管理员。先切换到admin库&#xff0c;然后通过命令创建数据库管理员账号和密码。最后再验证账号密码是否创建成功&#xff01; use admin db.createUser({user:"root",pwd:"123456Ab",…

《昇思25天学习打卡营第19天|Diffusion扩散模型》

什么是Diffusion Model&#xff1f; 什么是Diffusion Model? 如果将Diffusion与其他生成模型&#xff08;如Normalizing Flows、GAN或VAE&#xff09;进行比较&#xff0c;它并没有那么复杂&#xff0c;它们都将噪声从一些简单分布转换为数据样本&#xff0c;Diffusion也是从…

共建特色基地 协同互促育人

作为芯片和集成电路、人工智能、智能网联车等临港重点产业布局的知识密集型相关企业&#xff0c;核心技术人才和技术骨干是公司参与全球竞争的重要核心竞争力之一。 知从科技通过不断的创新和规范&#xff0c;在深化产教融合、校企合作、“双师型”、联合办学协同育人、产业人…

Java 中怎么解决 0.1 + 0.2 不等于 0.3?

&#x1f446;&#x1f3fb;&#x1f446;&#x1f3fb;&#x1f446;&#x1f3fb;关注博主&#xff0c;让你的代码变得更加优雅。 前言 Hutool 是一个小而全的Java工具类库&#xff0c;通过静态方法封装&#xff0c;降低相关API的学习成本&#xff0c;提高工作效率&#xf…

git回退分支版本git reset --hard HEAD

git回退分支版本git reset --hard HEAD git reset --hard HEAD 上面命令清除本地所有修改&#xff0c;与下面相似&#xff1a; git reset --hard origin/master 等同于&#xff1a; git reset --hard HEAD~0 说明&#xff1a; HEAD 当前版本 HEAD^ 上一个版本 HEAD^^ 上上…

单例模式 饿汉式和懒汉式的区别

单例模式&#xff08;Singleton Pattern&#xff09;是设计模式中最简单、最常见、最容易实现的一种模式。它确保一个类仅有一个实例&#xff0c;并提供一个全局访问点。单例模式主要有两种实现方式&#xff1a;饿汉式&#xff08;Eager Initialization&#xff09;和懒汉式&am…