我要投搞

标签云

收藏小站

爱尚经典语录、名言、句子、散文、日志、唯美图片

当前位置:四肖中特 > 反向复用 >

Nginx - proxy_配置 UDP的反向代理

归档日期:06-11       文本归类:反向复用      文章编辑:爱尚语录

  在实时性要求较高的特殊场景下,简单的UDP协议仍然是我们的主要手段。UDP协议没有重传机制,还适用于同时向多台主机广播,因此在诸如多人会议、实时竞技游戏、DNS查询等场景里很适用,视频、音频每一帧可以允许丢失但绝对不能重传,网络不好时用户可以容忍黑一下或者声音嘟一下,如果突然把几秒前的视频帧或者声音重播一次就乱套了。使用UDP协议作为信息承载的传输层协议时,就要面临反向代理如何选择的挑战。通常我们有数台企业内网的服务器向客户端提供服务,此时需要在下游用户前有一台反向代理服务器做UDP包的转发、依据各服务器的实时状态做负载均衡,而关于UDP反向代理服务器的使用介绍网上并不多见。本文将讲述udp协议的会话机制原理,以及基于nginx如何配置udp协议的反向代理,包括如何维持住session、透传客户端ip到上游应用服务的3种方案等。

  许多人眼中的udp协议是没有反向代理、负载均衡这个概念的。毕竟,udp只是在IP包上加了个仅仅8个字节的包头,这区区8个字节又如何能把session会话这个特性描述出来呢?

  物理层专注于提供物理的、机械的、电子的数据传输,但这是有可能出现差错的;

  数据链路层在物理层的基础上通过差错的检测、控制来提升传输质量,并可在局域网内使数据报文跨主机可达。这些功能是通过在报文的前后添加Frame头尾部实现的,如上图所示。每个局域网由于技术特性,都会设置报文的最大长度MTU(Maximum Transmission Unit),用netstat -i(linux)命令可以查看MTU的大小:

  而IP网络层的目标是确保报文可以跨广域网到达目的主机。由于广域网由许多不同的局域网,而每个局域网的MTU不同,当网络设备的IP层发现待发送的数据字节数超过MTU时,将会把数据拆成多个小于MTU的数据块各自组成新的IP报文发送出去,而接收主机则根据IP报头中的Flags和Fragment Offset这两个字段将接收到的无序的多个IP报文,组合成一段有序的初始发送数据。IP报头的格式如下图所示:

  IP协议头(本文只谈IPv4)里最关键的是Source IP Address发送方的源地址、Destination IP Address目标方的目的地址。这两个地址保证一个报文可以由一台windows主机到达一台linux主机,但并不能决定一个chrome浏览的GET请求可以到达linux上的nginx。

  4、传输层主要包括TCP协议和UDP协议。这一层最主要的任务是保证端口可达,因为端口可以归属到某个进程,当chrome的GET请求根据IP层的destination IP到达linux主机时,linux操作系统根据传输层头部的destination port找到了正在listen或者recvfrom的nginx进程。所以传输层无论什么协议其头部都必须有源端口和目的端口。例如下图的UDP头部:

  TCP的报文头比UDP复杂许多,因为TCP除了实现端口可达外,它还提供了可靠的数据链路,包括流控、有序重组、多路复用等高级功能。由于上文提到的IP层报文拆分与重组是在IP层实现的,而IP层是不可靠的所有数组效率低下,所以TCP层还定义了MSS(Maximum Segment Size)最大报文长度,这个MSS肯定小于链路中所有网络的MTU,因此TCP优先在自己这一层拆成小报文避免的IP层的分包。而UDP协议报文头部太简单了,无法提供这样的功能,所以基于UDP协议开发的程序需要开发人员自行把握不要把过大的数据一次发送。

  对报文有所了解后,我们再来看看UDP协议的应用场景。相比TCP而言UDP报文头不过8个字节,所以UDP协议的最大好处是传输成本低(包括协议栈的处理),也没有TCP的拥塞、滑动窗口等导致数据延迟发送、接收的机制。但UDP报文不能保证一定送达到目的主机的目的端口,它没有重传机制。所以,应用UDP协议的程序一定是可以容忍报文丢失、不接受报文重传的。如果某个程序在UDP之上包装的应用层协议支持了重传、乱序重组、多路复用等特性,那么他肯定是选错传输层协议了,这些功能TCP都有,而且TCP还有更多的功能以保证网络通讯质量。因此,通常实时声音、视频的传输使用UDP协议是非常合适的,我可以容忍正在看的视频少了几帧图像,但不能容忍突然几分钟前的几帧图像突然插进来:-)

  有了上面的知识储备,我们可以来搞清楚UDP是如何维持会话连接的。对话就是会话,A可以对B说话,而B可以针对这句话的内容再回一句,这句可以到达A。如果能够维持这种机制自然就有会话了。UDP可以吗?当然可以。例如客户端(请求发起者)首先监听一个端口Lc,就像他的耳朵,而服务提供者也在主机上监听一个端口Ls,用于接收客户端的请求。客户端任选一个源端口向服务器的Ls端口发送UDP报文,而服务提供者则通过任选一个源端口向客户端的端口Lc发送响应端口,这样会话是可以建立起来的。但是这种机制有哪些问题呢?

  问题一定要结合场景来看。比如:1、如果客户端是windows上的chrome浏览器,怎么能让它监听一个端口呢?端口是会冲突的,如果有其他进程占了这个端口,还能不工作了?2、如果开了多个chrome窗口,那个第1个窗口发的请求对应的响应被第2个窗口收到怎么办?3、如果刚发完一个请求,进程挂了,新启的窗口收到老的响应怎么办?等等。可见这套方案并不适合消费者用户的服务与服务器通讯,所以视频会议等看来是不行。

  有其他办法么?有!如果客户端使用的源端口,同样用于接收服务器发送的响应,那么以上的问题就不存在了。像TCP协议就是如此,其connect方的随机源端口将一直用于连接上的数据传送,直到连接关闭。

  这个方案对客户端有以下要求:不要使用sendto这样的方法,几乎任何语言对UDP协议都提供有这样的方法封装。应当先用connect方法获取到socket,再调用send方法把请求发出去。这样做的原因是既可以在内核中保存有5元组(源ip、源port、目的ip、目的端口、UDP协议),以使得该源端口仅接收目的ip和端口发来的UDP报文,又可以反复使用send方法时比sendto每次都上传递目的ip和目的port两个参数。

  对服务器端有以下要求:不要使用recvfrom这样的方法,因为该方法无法获取到客户端的发送源ip和源port,这样就无法向客户端发送响应了。应当使用recvmsg方法(有些编程语言例如python2就没有该方法,但python3有)去接收请求,把获取到的对端ip和port保存下来,而发送响应时可以仍然使用sendto方法。

  Nginx的stream系列模块核心就是在传输层上做反向代理,虽然TCP协议的应用场景更多,但UDP协议在Nginx的角度看来也与TCP协议大同小异,比如:nginx向upstream转发请求时仍然是通过connect方法得到的fd句柄,接收upstream的响应时也是通过fd调用recv方法获取消息;nginx接收客户端的消息时则是通过上文提到过的recvmsg方法,同时把获取到的客户端源ip和源port保存下来。我们先看下recvmsg方法的定义:

  其中msg_name就是对端的源IP和源端口(指向sockaddr结构体)。以上是C库的定义,其他高级语言类似方法会更简单,例如python里的同名方法是这么定义的:

  UDP协议自身并没有会话保持机制,nginx于是定义了一个非常简单的维持机制:客户端每发出一个UDP报文,通常期待接收回一个报文响应,当然也有可能不响应或者需要多个报文响应一个请求,此时proxy_responses可配为其他值。而proxy_timeout则规定了在最长的等待时间内没有响应则断开会话。

  最后我们来谈一谈经过nginx反向代理后,upstream服务如何才能获取到客户端的地址?如下图所示,nginx不同于IP转发,它事实上建立了新的连接,所以正常情况下upstream无法获取到客户端的地址:

  上图虽然是以TCP/HTTP举例,但对UDP而言也一样。而且,在HTTP协议中还可以通过X-Forwarded-For头部传递客户端IP,而TCP与UDP则不行。Proxy protocol本是一个好的解决方案,它通过在传输层header之上添加一层描述对端的ip和port来解决问题,例如:

  但是,它要求upstream上的服务要支持解析proxy protocol,而这个协议还是有些小众。最关键的是,目前nginx对proxy protocol的支持则仅止于tcp协议,并不支持udp协议,我们可以看下其代码:

  图5 nginx作为四层反向代理向upstream展示客户端ip时的ip透传方案

  除了上述方案外,还有个Direct Server Return方案,即upstream回包时nginx进程不再介入处理。这种DSR方案又分为两种,第1种假定upstream的机器上没有公网网卡,其解决方案图示如下:

  2、与第一种方案相同,修改upstream的默认网关为nginx所在机器(任何一台拥有公网的机器都行)。

  DSR的另一套方案是假定upstream上有公网线路,这样upstream的回包可以直接向client发送,如下图所示:

  这套DSR方案与上一套DSR方案的区别在于:由upstream服务所在主机上修改发送报文的源地址与源端口为nginx的ip和监听端口,以使得client可以接收到报文。例如:

  以上三套方案皆可以使用开源版的nginx向后端服务传递客户端真实IP地址,但都需要nginx的worker进程跑在root权限下,这对运维并不友好。从协议层面,可以期待后续版本支持proxy protocol传递客户端ip以解决此问题。在当下的诸多应用场景下,除非业务场景明确无误的拒绝超时重传机制,否则还是应当使用TCP协议,其完善的流量、拥塞控制都是我们必须拥有的能力,如果在UDP层上重新实现这套机制就得不偿失了。

  1案例1:Nginx反向代理1.1问题使用Nginx实现Web反向代理功能,实现如下功能:后端Web服务器两台,可以使用httpd实现Nginx采用轮询的方式调用后端Web服务器两台Web服务器的权重...博文来自:不忘初心

  业务场景是有大量客户端通过UDP端口上传一条数据到服务器,然后服务器给与应答。 服务部署在多台机器上,目前想通过NG做反向代理,使用了stream模块,发现在server段直连负载机时无异常: ser论坛

  我们很自豪地宣布,除了开源NGINX和我们的应用交付平台--NGINIXPlus,增加了一个激动人心的新能力-UDP负载均衡。这一新功能建立在我们现有的TCP和HTTP功能,使得NGINX成为一个功能...博文来自:用心做事

  这个模块可以实现基于TCP、UDP和Unix域的socket的协议的代理服务。这个模块是在nginx-1.9以后版本才添加的模块,如果要使用这个模块的话,要重新编译这个源代码,参考之前的的博客ngin...博文来自:youbingchen的博客

  nginx安装以及反向代理设置及参数设置优化更多干货更多干货 分布式实战(干货) springcloud实战(干货) mybatis实战(干货) springboot实战(干货) Re...博文来自:架构师的成长之路的博客

  简介LNMT=Linux+Nginx+MySQL+Tomcat;Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器;在中小型系统和并发访问用户不是很多的场合下被普遍使用,...博文来自:遥望......

  这个模块可以转发请求到其他的服务器。HTTP/1.0无法使用keepalive(后端服务器将为每个请求创建并且删除连接)。nginx为浏览器发送HTTP/1.1并为后端服务器发送HTTP/1.0,这样...博文来自:remotesupport的专栏

  Nginx标签:nginx代理代理服务可简单的分为正向代理和反向代理:正向代理:用于代理内部网络对Internet的连接请求(如VPN/NAT),客户端指定代理服务器,并将本来要直接发送给目标Web服...博文来自:菜鸟-翡青

  从昨晚到现在,不停的修改编译,终于编译成功了,不过把一些选项去掉了,不知道执行还有没有问题。中文参考博文来自:liswa 电脑备忘录

  前提条件创建虚拟机一台nginx,1台或者2台tomcat1台的线个tomcat的端口号要改一下2台就不用改端口号了我这用2台tomcat,这三个虚拟机的ip肯定要在同意网段是吧nginx:19...博文来自:reee112的博客

  本次应用的目的是拿nginx做服务器的负载均衡,而且提供的服务已用docker进行部署,该docker提供访问的端口有两个,分别对应不同的服务。因此首先需要查看docker映射的端口,然后通过修改up...博文来自:专注挖坑

  前面一篇文章只是简单使用了一些nginx的http代理,大家可以看到,非常的easy。只要对f稍作简单的配置就可以实现http反向代理了。但是我们现在的应用场景不一样,我们现在需要t...博文来自:oldmtn的专栏

  1. 什么是代理服务器1.1. 代理服务器的好处代理服务器架构1)提高访问速度由于目标主机返回的数据会存放在代理服务器的硬盘中,因此下一次客户再访问相同的站点数据时,会直接从代理服务器的硬盘中读取,起...博文来自:wyp584168的专栏

  UDP协议:面向非连接的协议。指在正式通信前不必与对方先建立连接,不管对方状态就直接发送。对方是否可以接受这些内容,该协议则无法控制。适用于:一次性只传输少量数据、对可靠性要求不高的应用环境。UDP和...博文来自:u012309611的专栏

  主要功能在于:TCP/UDP是在第四层的传输协议,而web是会话层面的应用,所有实现TCP/UDP的调动,可以使得nginx支持更多的运用,比如对ssh。但是 nginx1.9之前只支持http,之后...博文来自:朱海燕的博客日记

  Nginx配置UDP负载在我们平常的网络性能需求中,大多都是HTTP负载,当然这些是也是主流,但是我们有时也需要UDP协议的负载如dns何ntp的信息,现在在1.9版本后加入了UDP负载。本人是基于r...博文来自:Linux学习与应用

  简介:代理服务可简单的分为正向代理和反向代理:正向代理:用于代理内部网络对Internet的连接请求(如VPN/NAT),客户端指定代理服务器,并将本来要直接发送给目标Web服务器的HTTP请求先发送...博文来自:BLXH-AS

  配置Nginx反向代理FRPS服务端口文章作用根据最后的效果图,我们可以看到省去了端口号访问,直接用域名访问内网中的项目,方便好记!Nginx简介开放源代码的高性能HTTP服务器和反向代理服务器,同时...博文来自:forwardlee的博客

  Nginx反向代理(单Server多端口实现)1 需求实现通过同一个域名根据不同接口访问分别Tomcat和Apache服务器2 反向代理实现思路3 开发环境准备注意:Tomcat直接使用Springb...博文来自:weixin_43881335的博客

  最近在折腾转发tcp请求,原本我是用的是HAproxy,换了服务器之后本来想继续使用HAproxy的,不知怎么的在阴差阳错之下查到了nginx(版本号在1.11之后的)也支持tcp、udp请求的转发和...博文来自:雷鸣II

  udp的负载需要使用nginx的stream模块,请实现检查是否已经安装具体配置文件:udp的负载需要使用nginx的stream模块,请实现检查是否已经安装具体配置文件:#LoadbalanceUD...博文来自:weixin_34248118的博客

  Nginx中发送udp请求最近简单了解了一下Nginx发送udp请求的过程,在这里简单记录一下.主要参考的代码主要有两块,分别是ngx_resolver.c以及agentzh的ngx_lua模块中的u...博文来自:阳光梦的专栏

  Nginx反向代理模式下出现页面加载不全,或直接出现502badgateway的情况。出现502badgateway的情况有很多,大多是一些nginx相关timeout的设置问题。下文讨论一种比较少见...博文来自:wh1511995112的博客

  #######准备3台虚拟机代理机器:两块网卡(一块桥接,一块hostonly),桥接的ip自动获得即可。hostonly的网卡ip设置成172.16.0.1/16(这个IP随意,注意这个ip是下边两...

  Intellij IDEA 如何通过数据库表生成带注解的实体类图文详细教程06-08阅读数 2万+

  jquery/js实现一个网页同时调用多个倒计时(最新的)11-25阅读数 54万+

  FFFSSSFFF6:你好,16进制转有符号好像不对啊,输入ff 变成 -1

本文链接:http://pebeducation.com/fanxiangfuyong/378.html