如何将TCP通信复制到一台或多台远程服务器以进行基准测试?


30

基础设施:数据中心中的服务器,OS-Debian Squeeze,Web服务器-Apache 2.2.16


情况:

我们的客户每天都在使用实时服务器,因此无法测试调整和改进。因此,我们想将实时服务器上的入站HTTP通信实时复制到一个或多个远程服务器。流量必须传递到本地Web服务器(在本例中为Apache)和远程服务器。因此,我们可以调整配置,并在远程服务器上使用不同/更新的代码进行基准测试,并与当前的实时服务器进行比较。目前,网络服务器正在监听大约。由于客户端结构,除了80和443之外,还增加了60个端口。


问题:如何实现与一台或多台远程服务器的重复?

我们已经尝试过:

我们在这里用尽所有选项。

使用IPTABLES时,是否有方法可以禁用TEE功能的“本地网络中的服务器”的实施?

通过使用IPTABLES或路由可以实现我们的目标吗?

您是否知道为此目的测试过并且可以在这些特定情况下使用的其他工具?

tee-proxy是否有其他来源(完全适合我们的要求,AFIAK)?


提前感谢您的回复。

----------

编辑:05.02.2014

这是python脚本,它将按照我们需要的方式起作用:

import socket  
import SimpleHTTPServer  
import SocketServer  
import sys, thread, time  

def main(config, errorlog):
    sys.stderr = file(errorlog, 'a')

    for settings in parse(config):
        thread.start_new_thread(server, settings)

    while True:
        time.sleep(60)

def parse(configline):
    settings = list()
    for line in file(configline):
        parts = line.split()
        settings.append((int(parts[0]), int(parts[1]), parts[2], int(parts[3])))
    return settings

def server(*settings):
    try:
        dock_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        dock_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        dock_socket.bind(('', settings[0]))

        dock_socket.listen(5)

        while True:
            client_socket = dock_socket.accept()[0]

            client_data = client_socket.recv(1024)
            sys.stderr.write("[OK] Data received:\n %s \n" % client_data)

            print "Forward data to local port: %s" % (settings[1])
            local_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            local_socket.connect(('', settings[1]))
            local_socket.sendall(client_data)

            print "Get response from local socket"
            client_response = local_socket.recv(1024)
            local_socket.close()

            print "Send response to client"
            client_socket.sendall(client_response)
            print "Close client socket"
            client_socket.close()

            print "Forward data to remote server: %s:%s" % (settings[2],settings[3])
            remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            remote_socket.connect((settings[2], settings[3]))
            remote_socket.sendall(client_data)       

            print "Close remote sockets"
            remote_socket.close()
    except:
        print "[ERROR]: ",
        print sys.exc_info()
        raise

if __name__ == '__main__':
    main('multiforwarder.config', 'error.log')

使用此脚本的注释:
该脚本将许多已配置的本地端口转发到另一个本地和远程套接字服务器。

配置:
将配置文件添加到配置文件port-forward.config中,内容如下:

错误消息存储在文件“ error.log”中。

该脚本将分割配置文件的参数:
用空格分割每个配置行
0:侦听
本地端口1:本地端口转发到
2:目标服务器的远程IP地址
3:目标服务器的远程端口
并返回设置


所有的流量都是HTTP吗?
longneck 2014年

是的,所有流量都是HTTP。
Sise 2014年

1
顺便说一句 teeproxy可以在这里找到:github.com/chrislusf/teeproxy
Tombart

1
另一种可能性:github.com/ebowman/splitter Scala / Netty-based。
Rich K.

Answers:


11

是不可能的。TCP是全状态协议。用户终端计算机参与了连接的每个步骤,它将永远不会响应试图与之通信的两个单独的服务器。您所能做的就是在网络服务器或某个代理上收集所有http请求,然后重播它们。但这不会给出实时服务器的确切并发性或流量条件。


复制TCP是不可能的-我会同意这一点。没有复制第7层流量。您可以捕获来自客户端的请求,并将其播放回其他服务器。每个TCP会话播放简单的1个请求应该很容易。持久连接在您如何计时客户端的其他请求方面将需要一些思考。
埃文·安德森

@Kazimieras Aliulis:不需要与两个单独的服务器进行通信。客户端正在与主服务器=实时服务器通信。实时服务器正在处理客户端请求并正在响应客户端。除了处理和应答客户端外,主服务器还将请求复制到第二台服务器=测试服务器。从第二个服务器到主服务器的响应将在主服务器上被丢弃/忽略,并且不会转发给客户端。
Sise 2014年

@Evan Anderson:在HTTP级别上进行复制也是我们的第一个想法,但是例如apache代理或类似工具或模块不允许同时在本地处理请求并将其复制到远程主机。如果您还有其他想法,请指教!:)我们更喜欢复制而不是录制和重放,以获得即时的比较结果。
Sise 2014年

1
@Sise:您可以尝试编写自己的http代理,该代理将流量传递到两个服务器。使用python Twisted框架twistedmatrix.com应该很容易做到。
Kazimieras Aliulis 2014年

@Kazimieras Aliulis:绝对是另一种选择!我从来没听说过。但将其检出表明它完全符合我们的目的。我们之前没有考虑过python,但是目前我们正在研究Twisted框架以及通用python的可能性。如果成功,我会回报!
Sise 2014年


7

Teeproxy可用于复制流量。用法非常简单:

./teeproxy -l :80 -a localhost:9000 -b localhost:9001
  • a 生产服务器
  • b 测试服务器

将HAproxy(带有roundrobin)放在您的Web服务器之前,您可以轻松地将50%的流量重定向到测试站点:

         /------------------> production
HAproxy /                 ^
        \                /
         \---- teeproxy -.....> test (responses ignored)

4

@KazimierasAliulis指出,TCP是一种有状态协议,不能简单地将数据包的副本放到另一个主机上。

在TCP终止层拾取数据包并将其作为新的TCP流中继是合理的。您链接到的复制器工具似乎是您的最佳选择。它作为TCP代理运行,从而允许TCP状态机正常运行。来自测试机器的响应将被丢弃。听起来像它完全符合您的需求。

对我来说尚不清楚,为什么您将复制器工具注销为不可接受的。由于该工具仅侦听单个端口,因此您将必须运行该工具的多个实例,但是,大概您希望将这些不同的侦听端口中的每个中继到后端系统上的不同端口。如果没有,您可以使用iptables DNAT将所有侦听端口定向到复制器工具的单个侦听副本。

除非您要测试的应用程序很简单,否则我希望您会遇到这种与时序和内部应用程序状态有关的测试方法的问题。您想做的事情听起来很简单-我希望您会发现很多边缘情况。


是的,您完全正确,除多端口情况外,agnoster复制器工具将符合我们的要求。同样,完全放弃了测试机的响应。为了实现我们尽可能准确地模拟真实/实时情况的目标,我们不能将实时服务器上的所有端口捆绑到测试计算机上的单个端口。使用不同的端口将客户端设备划分为不同的客户。因此,我们必须打开此复制器工具的60-70个会话。可以想象,这不是很实用。
Sise 2014年

@Sise-计算机擅长做乏味的事情。我认为您可以编写一个脚本来解析您的Apache配置并吐出必要的命令行以运行复制器工具的60-70个实例。我无法想象复制器工具会占用大量资源,但是即使如此,您也可以在另一台计算机上运行60-70个实例,并做一些网络欺骗来获得流量。至少对我来说,这似乎是完全可行的,并且是解决此问题的非常简单的方法。
Evan Anderson

1

我正在尝试做类似的事情,但是,如果您只是想模拟服务器上的负载,我会看一看类似负载测试框架的内容。我过去使用过locust.io,它在模拟服务器上的负载方面非常有效。这样一来,您就可以模拟大量客户端,并可以处理服务器的配置,而不必经历将流量转发到另一台服务器的痛苦过程。


0

至于“我们想将实时服务器上的入站HTTP通信实时复制到一个或多个远程服务器上”,上面没有提到的一种方法是在它所连接的交换机上配置一个镜像端口。

在Cisco Catalyst交换机的情况下,这称为SPAN(更多信息在此处)。在思科环境中,您甚至可以将镜像端口放在其他交换机上。

但这是为了进行流量分析,因此在上面第一段的引用文本中,它将是单向关键字:inbound。我认为该端口不会允许任何回程通信,如果允许,您将如何处理重复的回程通信?那可能只会对您的网络造成破坏。

所以...只是想将一种可能性添加到您的列表中,但请注意,这确实是单向流量。也许您可以在该镜像端口上放置一个集线器,并由某些本地客户端模拟器处理重复的服务器回复,这些回复将拾取启动的会话并进行响应,但随后您会将传入的流量复制到重复的服务器...可能不是您所需要的想。


我们已经考虑过这一点,我已经阅读了使用SPAN的替代方法。但是,由于服务器位于第三方提供商的数据中心内,因此涉及硬件更改的可能性有限。我已经请求直接在第二个NIC上连接2个服务器。只需将这两个服务器与本地网络结合使用,便可以将IPTABLES与TEE结合使用。但是要采用这种替代方法,我们将需要更改服务器的外部IP,这是NoGo,因为将客户端设备配置为连接到设置的IP。
Sise 2014年

0

我还为Node.js编写了一个类似的反向代理/负载平衡器(这只是出于娱乐目的,目前还不能用于生产)。

https://github.com/losnir/ampel

它很自以为是,目前支持:

  • GET 使用循环选择(1:1)
  • POST使用请求拆分。没有“主”和“影子”的概念-响应的第一个后端是将服务于客户端请求的后端,然后所有其他响应都将被丢弃。

如果有人发现它有用,那么我可以改进它以使其更加灵活。


对于这样的应用程序,Node.js是一种非常奇怪的语言选择,这将需要非常高的性能。我不确定这是否可以投入生产。
迈克尔·汉普顿

你是绝对正确的。这并不是要表现出色-只是易于编写(对我而言)。我认为这取决于所需的负载。尽管在低端计算机(2核)上,我还是可以达到1,000rps以上的一点。
losnir '18

0

我的公司有类似的要求,即克隆一个数据包并将其发送到另一台主机(我们运行市场数据模拟器,并且需要一个临时解决方案,该解决方案可以侦听市场数据TCP提要,获取每个数据包但还将每个数据包的克隆发送至另一个模拟器服务器)

这个二进制文件运行得很好,它是TCP Duplicator的一个版本,但是用golang而不是jscript编写,因此它的运行速度更快,并且可以像宣传的那样工作,

https://github.com/mkevac/goduplicator


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.