什么是反向代理?它有哪几类?

分类: 架构设计

保留所有版权,请引用而不是转载本文(原文地址 https://yeecode.top/blog/137/ )。

经过内容分发网络或者多地址直连方式的分流后,用户的请求已经分散到了不同的系统上。这里所说的一个系统,是指它对外呈现唯一的 IP 地址。

通常来说,一个确定的 IP 地址会代表一台确定的机器(节点),但这不是绝对的。通过代理,可以让多个节点对外表现出唯一的 IP 地址。

代理是软件架构和网络设计里都常接触的概念。例如,用户端可以设置代理服务器,让所有请求都由代理服务器发出。这样一来,从外部看,所有请求都由代理服务器发出,无法判断它背后代理了多少用户端。这种代理方式叫作正向代理,如图 1所示。

正向代理示意图
图 1:正向代理示意图

同样的,服务端也可以设置代理服务器。所有请求都由代理服务器接收,再由它分发给后方的服务器。这样一来,从外部看,所有请求都由代理服务器处理,无法判断它后方到底有多少服务器。这种代理方式叫作反向代理,如图 2所示。

反向代理示意图
图 2:反向代理示意图

反向代理可以用来对请求进行分流,把请求分流到系统内部的多个节点上,从而减少每个节点的并发数。而这些节点在外界看来是一个系统,表现出唯一确定的 IP。

实现反向代理的手段有很多,可以根据它工作的层级不同分为两类:四层反向代理和七层反向代理。这里说的层级,是 OSI 参考模型的层级。OSI 参考模型把通信功能划分为七个层次,每一层向相邻上层提供一套确定的服务,并使用相邻下层提供的服务实现当前层级的功能和协议。OSI 参考模型的层级划分和各层功能如图 3所示。

OSI参考模型
图 3:OSI参考模型

在 OSI 参考模型中,第四层是传输层,TCP 协议和 UDP 协议等工作在这一层;第七层是应用层,HTTP 协议和 FTP 协议等工作在这一层。了解这些之后,就能理清楚四层和七层反向代理的工作原理:

  • 四层反向代理:可以根据用户请求的 IP 和端口号进行转发。
  • 七层反向代理:可以根据 FTP 请求、HTTP 请求中的具体内容进行转发,例如根据 HTTP 请求的请求方法、URL、请求首部、请求正文等信息进行转发。

四层反向代理处在 OSI 协议的更底层,掌握的信息更少,因此实现原理更简单,运行效率也更高。七层反向代理工作在应用层,能收集到更多信息,因此可以做得更智能。例如,它可以分析请求的 cookie 信息,针对不同 cookie 做不同处理;也可以分析请求的 URL,把针对特殊资源(例如图像资源)的请求转发到特定服务器上。当然,获取全面信息的代价是牺牲效率,相比于四层反向代理,七层反向代理实现更复杂、效率也更低。

在对系统请求进行内部分流时,七层反向代理应用得最为广泛。因为它可以对外表现出完全一致的 IP 地址和端口,再根据请求的具体内容分流。Nginx 就是一种典型的七层反向代理软件。下面以 Nginx 为例,简要介绍反向代理的实现。

使用 Nginx 搭建反向代理时,主要用它的 upstream 模块。upstream 即"上游"的意思,指 Nginx 后方的服务节点,Nginx 只需要把请求以某种策略转发给后方节点即可。

利用 Nginx 的转发策略,可以实现后方服务节点间的负载均衡。Nginx 支持的策略有轮询、加权轮询、请求源 IP 地址哈希,此外还支持用户自己扩展策略。其中轮询是指平均地为后方节点分配请求;加权轮询是指按一定比例分配;请求源 IP 地址哈希是指根据请求来源 IP 的哈希结果分配。这种哈希策略有个优点:只要请求方 IP 不变,服务它的后方节点也不变,这有利于维护 Session 等信息。

Nginx 的配置在它的 nginx.conf 文件中。下面这段配置表示 Nginx 监听自身 80 端口,收到路径以"/“开头的请求时,以 1:2 的比例转发给名为"yeecode.top"的上游组中的两个服务节点处理。

http 
{ 
  # 这是一个虚拟的主机,该主机监听localhost:80
  server 
  { 
    listen    80; 
    server_name localhost; 
    root html; 
    index index.html index.htm; 

    # 如果请求的地址为"/"开头,则转发到yeecode.top
    location ^~ / 
    { 
      proxy_pass http://yeecode.top; 
    }    
  } 

  # 设置一组上游服务器
  upstream yeecode.top 
  { 
      server 192.168.2.1:80 weight=1; 
      server 192.168.2.2:80 weight=2; 
  } 
} 

上面这段反向代理转发策略是固化在配置文件中的。Nginx 也可以通过嵌入脚本的方式动态完成请求转发。在下面这段配置中,Nginx 遇到路径以”/abouts/“开头的请求时会调用 lua 脚本,再根据脚本给出的结果跳转。这样我们可以在脚本里完成分析请求详情、查询数据库等复杂操作,实现更灵活的转发。

location ^~ /abouts/ { 
  access_log off; 
  
  #定义一个变量 
  set $app_proxy ""; 
  
  #调用了lua脚本 
  access_by_lua_file "router.lua"; 
  
  #按照lua脚本给出的变量值跳转 
  proxy_pass http://$app_proxy; 
 } 

反向代理使得请求在到达系统内部后仍然可以被继续分流,这为后面要讲的服务并行设计创造了条件。


在 AI 编程迅猛发展的今天,编码能力逐步弱化,而架构能力则成了开发者更核心的竞争力。聊完反向代理,以及它如何把请求在系统内部继续分流,如果你对这类架构设计感兴趣,推荐一本书《高性能架构之道(第二版)》。

这是一本理论联系实际的架构书,系统讲了怎么从顶层把软件架构好:覆盖分布式、并发编程、数据库调优、缓存、IO、高可用、前端性能优化等众多知识,最后还拿一个真实项目完整走了一遍架构全过程,把书里的方法真正落了地。

高性能架构之道(第二版)

《高性能架构之道(第二版)》

这本书还在台湾地区出了繁体版,叫《巨型服务架构》——繁体版嘛,贵得有点离谱。

就先聊到这儿。

我是软件架构师易哥。可以关注我,我会偶尔冒个泡,分享点编程干货!

可以访问个人知乎阅读更多文章:易哥(https://www.zhihu.com/people/yeecode),欢迎关注。

作者书籍推荐

作者书籍推荐 作者书籍推荐