一 问题背景

0 Comments

最后,本文要构建代理网关,本质上就是一个非透明的上游代理,并给出详细的设计与实现。

透明代理是代理网关的基础,本文采用JAVA原生的NIO进行详细介绍。在实现代理网关时,实际使用的为NETTY框架。原生NIO的实现对理解NETTY的实现有帮助。

代理服务在收到连接请求时,判定:如果是CONNECT请求,需要回应代理连接成功消息到客户端;

CONNECT请求回应结束后,代理服务需要连接到CONNECT指定的远程服务器,然后直接转发客户端和远程服务通信;

代理服务在收到非CONNECT请求时,需要解析出请求的远程服务器,然后直接转发客户端和远程服务通信;

注意,此时代理服务代理了HTTPS请求,但是并不需要-k选项,指示非安全的代理。因为代理服务本身并没有作为一个中间人,并没有解析出客户端和远程服务端通信的内容。在非透明代理时,需要解决这个问题。

当传输为HTTP协议时,SocketPipe传输的数据即为明文的数据,可以拦截后直接做处理。

当传输为HTTPS协议时,SocketPipe传输的有效数据为加密数据,并不能透明处理。

另外,无论是传输的HTTP协议还是HTTPS协议,SocketPipe读到的都为非完整的数据,需要做聚批的处理。

透明代理需要响应 CONNECT请求,透明上游代理不需要,直接转发即可;

透明代理需要解析CONNECT请求中的HOST和PORT,并连接服务端;透明上游代理只需要连接下游代理的IP:PORT,直接转发请求即可;

透明的上游代理,只是一个简单的SocketChannel管道;确定下游的代理服务端,连接转发请求;

以上,分为四个组件:客户端,代理服务(ServerHandler),代理服务(ClientHandler),服务端

如果是HTTP的请求,数据直接通过 客户端-ServerHandler-ClientHandler-服务端,代理网关只需要做简单的请求聚批,就可以应用相应的管理策略;

如果是HTTPS请求,代理作为客户端和服务端的中间人,只能拿到加密的数据;因此,代理网关需要作为HTTPS的服务方与客户端通信;然后作为HTTPS的客户端与服务端通信;

代理作为HTTPS服务方时,需要考虑到其本身是个非透明的代理,需要实现非透明代理相关的协议;

代理作为HTTPS客户端时,需要考虑到其下游是个透明的代理,真正的服务方是客户端请求的服务方;

本文需要构建的是非透明上游代理,以下采用NETTY框架给出详细的设计实现。上文将统一代理网关分为两大部分,ServerHandler和ClientHandler,以下

首先解析HTTP请求,然后做聚批的处理,最后ServerChannelHandler实现代理网关协议;

如果下游是代理,那么会采用HttpProxyHandler,经由下游代理与远程服务端通信;

如果当前需要升级为SSL协议,会对SocketChannel做透明的封装,实现SSL通信。

最后,ClientChannelHandler只是简单消息的转发;唯一的不同是,由于代理网关拦截了第一个请求,此时需要将拦截的请求,转发到服务端。

代理通常面临的问题是OOM。本文在实现代理网关时保证内存中缓存时当前正在处理的HTTP/HTTPS请求体。内存使用的上限理论上为实时处理的请求数量*请求体的平均大小,HTTP/HTTPS的请求结果,直接使用堆外内存,零拷贝转发。

性能问题不应提早考虑。本文使用NETTY框架实现的代理网关,内部大量使用堆外内存,零拷贝转发,避免了性能问题。

使用IdleStateHandler定时监控空闲的TCP连接,强制关闭;解决了该问题。

代理网关的管理部分,可以在ServerHandler部分维护,也可以在ClientHandler部分维护;

注:本文使用Netty的零拷贝;存储请求以解析处理;但并未实现对RESPONSE的处理;也就是RESPONSE是直接通过网关,此方面避免了常见的代理实现,内存泄漏OOM相关问题;

最后,本文实现代理网关后,针对代理的资源和流经代理网关的请求做了相应的控制,主要包括:

标签:

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注