最近我们开发的一个APP,其中某个模块需要有ASR(语音转文字)的功能,对应的服务端是部署在阿里云上面的。ASR服务我们已经开发完成,但测试发现ASR在进行语音识别时,会消耗大量的资源(CPU、GPU、内存),特别是GPU,这样导致转换的延迟很大,为了能低延时运行ASR,我们为测试电脑专门配备了一块 NVIDIA RTX 3090的显卡,才能满足要求。
等到要正式发布时,问题来了:如果租一台能满足ASR要求的云服务器,费用就会很高。于是,我们想到了如下解决方案:在我们公司的局域网中找了一台高配的电脑来部署ASR服务,然后租一个低配的阿里云服务器作为代理对外暴露ASR服务,阿里云代理服务器会将ASR请求转到局域网内真正的ASR服务器来处理,这样整体费用就降下来了。这个方案的难点是,代理服务器要能将请求正常转发到局域网内,而局域网内的电脑是不对外的,这就需要解决内网穿透问题。为此,我们写了一个TCP反向代理来实现此目的。文末我们会将该TCP反向代理程序免费分享给大家使用(无任何限制),由于HTTP底层也是基于TCP的,所以该反向代理也适用于HTTP服务。
一. TCP反向代理的使用场景
TCP反向代理开发完成后,我们已经在两种场景中,将其用了起来。
(1)如上文提到的,为节省服务器成本,将硬件资源消耗巨大的服务部署在内网服务器上,而云服务器上只部署一个代理,这样高消耗的计算全部转发到内网服务器执行。
(2)跟客户远程联调程序时,我们的开发人员直接VS调试运行服务端程序,通过TCP反向代理将其对应的端口映射到阿里云服务器上,客户那边的客户端程序就直接连阿里云服务器的端口就可以了。
这样,断点调试能非常快地发现和解决bug,大大提高了联调效率。
二. TCP反向代理部署结构
TCP反向代理程序分为两个端:WAN端(即代理端,部署在公网服务器上)、LAN端(部署在局域网内的电脑上)。
以前面提到的ASR服务为例,我们在实现TCP反向代理程序后,将其按如下结构进行部署:

上图完整的展现了我们的ASR应用使用TCP反向代理的部署结构,其更详细说明如下。
1. 节点说明
(1)图中ASR.Client是真正的使用ASR服务的客户端程序,其分布在广域网中。
(2)图中ASR.Server是真正提供ASR服务的服务端程序,其部署在公司内网的高配电脑上。
(3)TcpReverser.WAN 和 TcpReverser.LAN 是TCP反向代理程序。
(4)TcpReverser.WAN 又名为 ProxyServer ,部署在公网的低配服务器上。
(5)TcpReverser.LAN 又名为 BridgeServer ,部署在公司内网的电脑上。
2. 端口说明
理解部署结构图中的每个端口的含义,才能正确的使用TCP反向代理程序。
(1)内网中 ASR.Server 提供ASR服务的端口是9000,映射到公网服务器对应的 ProxyServer 的工作端口也是9000。
(2)ProxyServer 另外还使用了两个TCP端口:3010和 3020。
(3)ProxyServer 的9100端口用于BridgeServer与其进行反向代理内部实现的交互通信。
(4)ProxyServer 的3020端口用于真正ASR业务数据的转发。
3. 转发原理
那么ASR客户端的请求是如何转发到内网的ASR服务器的了?
(1)首先,启动ProxyServer,再启动BridgeServer。
BridgeServer初始化时会与ProxyServer的9100端口建立TCP连接(我们姑且将其称为"协作连接"),后面将基于此连接进行与TCP反向代理相关的协作通信。
(2)当ProxyServer的9000端口监测到某个ASR客户端TCP连接上来时,就通过"协作连接"给BridgeServer发送通知。
(3)BridgeServer收到通知后,会与ProxyServer的3020端口建立一个新TCP连接(姑且称为"A连接 "),并与ASR.Server的9000端口建立一个新的TCP连接(姑且称为"B连接")。
(4)BridgeServer 将"A连接 "和"B连接"绑定成一个TCP连接对(ConnectionPair):将从连接对中的任何一个连接上接收到的任何数据都如实地转发到另一连接上。
(5)同时,ProxyServer 会将"A连接"和刚来自ASR客户端的TCP连接也绑定成一个TCP连接对:也将从连接对中的任何一个连接上接收到的任何数据都如实地转发到另一连接上。
(6)当ASR客户端与ProxyServer之间的TCP连接断开时,对应的"A连接 "和"B连接"也会被断开,连接对被释放。
(7)同理,当因为某些原因,"A连接 "或"B连接"断开时,BridgeServer 和 ProxyServer 会释放对应的连接对,这也意味着ProxyServer会断开对应的ASR客户端。
"B连接 "是在局域网内部,一般不会因为网络问题断开。但是,"A连接"是有可能的,所以,我们最好保障局域网到云服务器的网络是比较稳定可靠的。
三. 配置文件说明
在有了上面的基本概念之后,我们再来看TCP反向代理程序的ProxyServer 和BridgeServer的配置文件,就很容易理解了。
我们还是以上面的ASR服务的例子,来看看它所使用的TCP反向代理程序的配置信息。
1. ProxyServer 的配置
ProxyServer 其对应的配置文件是 TcpReverser.ProxyServer.dll.config。
<!--工作端口-->
<add key="WorkPort" value="9000"/>
<!--内部协作端口-->
<add key="IcPort" value="3010"/>
<!--转发数据端口-->
<add key="TransferPort" value="3020"/>
2. BridgeServer 的配置
BridgeServer 其对应的配置文件是 TcpReverser.BridgeServer.dll.config。
<!--ProxyServer服务器IP -->
<add key="ProxyServerIP" value="47.109.*.*"/>
<!--ProxyServer服务器内部协作端口-->
<add key="ProxyIcPort" value="3010"/>
<!--ProxyServer服务器转发端口-->
<add key="ProxyTransferPort" value="3020"/>
<!--真实服务器IP -->
<add key="RealServerIP" value="127.0.0.1"/>
<!--真实服务器端口-->
<add key="RealServerPort" value="9904"/>
四. 下载与运行
在阿里云服务器上启动ProxyServer,在内网电脑上启动ASR服务器 和 BridgeServer,然后用一个ASR客户端连接ProxyServer的9000端口。
ProxyServer 的终端运行的输出如下所示:

BridgeServer的终端运行的输出如下所示:

我们可以看到,当一个ASR客户端连接上来时,ProxyServer 和 BridgeServer 都分别创建了一个TCP连接对。这样,ASR客户端和ASR服务器之间就可以正常地双向传递数据了。
最后,附上TCP反向代理程序的下载链接:TcpReverser.rar
有需要的朋友可以用起来!欢迎大家留言交流!