벤치마킹 목적으로 하나 이상의 원격 서버에 TCP 트래픽을 복제하는 방법은 무엇입니까?


30

인프라 : 데이터 센터 서버, OS-데비안 스퀴즈, 웹 서버-Apache 2.2.16


상태:

라이브 서버는 고객이 매일 사용하므로 조정 및 개선 사항을 테스트 할 수 없습니다. 따라서 라이브 서버의 인바운드 HTTP 트래픽을 하나 이상의 원격 서버에 실시간으로 복제하려고합니다. 트래픽은 로컬 웹 서버 (이 경우 Apache) 및 원격 서버로 전달되어야합니다. 이를 통해 현재 라이브 서버와 벤치마킹 및 비교를 위해 원격 서버에서 구성을 조정하고 다른 / 업데이트 된 코드를 사용할 수 있습니다. 현재 웹 서버는 약을 듣고 있습니다. 클라이언트 구조로 인해 80 및 443 이외의 추가 포트 60 개.


질문 : 하나 또는 여러 원격 서버에 대한 이러한 복제를 어떻게 구현할 수 있습니까?

우리는 이미 시도했습니다 :

  • agnoster duplicator-포트 당 하나의 열린 세션이 필요하며 적용 할 수 없습니다. ( https://github.com/agnoster/duplicator )
  • kklis 프록시-트래픽을 원격 서버로만 전달하지만 lcoal 웹 서버로 전달하지는 않습니다. ( https://github.com/kklis/proxy )
  • iptables-DNAT는 트래픽을 전달 만하지만 로컬 웹 서버로 전달하지는 않습니다.
  • iptables-TEE가 로컬 네트워크의 서버에만 복제-> 데이터 센터의 구조로 인해 서버가 동일한 네트워크에 있지 않음
  • stackoverflow ( https://stackoverflow.com/questions/7247668/duplicate-tcp-traffic-with-a-proxy ) 에서 "프록시와 함께 tcp 트래픽 복제"라는 질문에 제공된 대안 이 실패했습니다. 언급했듯이 TEE는 로컬 네트워크 외부의 원격 서버에서는 작동하지 않습니다. teeproxy는 더 이상 사용할 수 없으며 ( https://github.com/chrislusf/tee-proxy ) 다른 곳에서는 찾을 수 없습니다.
  • 동일한 네트워크에있는 두 번째 IP 주소를 추가하고 eth0 : 0에 할당했습니다 (1 차 IP 주소는 eth0에 할당). 이 새로운 IP 또는 가상 인터페이스 eth0 : 0을 iptables TEE 기능 또는 라우트와 결합하는 데 성공하지 못했습니다.
  • "debian squeeze에서 중복 수신 TCP 트래픽 "( Debian Squeeze에서 중복 수신 TCP 트래픽) 질문에 제공된 대체 제안 이 실패했습니다. cat | nc 세션 (cat / tmp / prodpipe | nc 127.0.0.1 12345 및 cat / tmp / testpipe | nc 127.0.0.1 23456)은 통지 또는 로그없이 클라이언트에 의한 모든 요청 / 연결 후에 중단됩니다. Keepalive는이 상황을 바꾸지 않았습니다. TCP 패키지가 원격 시스템으로 전송되지 않았습니다.
  • socat의 다른 옵션으로 추가 시도 (방법 : http://www.cyberciti.biz/faq/linux-unix-tcp-port-forwarding/ , https://stackoverflow.com/questions/9024227/duplicate-input- 제공된 TEE 기능이 FS에만 쓰기 때문에 unix-stream-to-multiple-tcp-clients-using-socat ) 및 유사한 도구가 실패했습니다.
  • 물론이 "문제"또는 설정에 대한 인터넷 검색 및 검색도 실패했습니다.

옵션이 부족합니다.

IPTABLES를 사용할 때 TEE 기능의 "로컬 네트워크의 서버"시행을 비활성화하는 방법이 있습니까?

IPTABLES 또는 경로를 다르게 사용하여 목표를 달성 할 수 있습니까?

테스트를 거쳐 이러한 특정 상황에서 작동하는 다른 용도의 도구를 알고 있습니까?

티 프록시에 대한 다른 소스가 있습니까 (AFAIK의 요구 사항에 완벽하게 부합 함)?


답장을 보내 주셔서 감사합니다.

----------

편집 : 05.02.2014

다음은 파이썬 스크립트이며, 필요한 방식으로 작동합니다.

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

예, 모든 트래픽은 HTTP입니다.
Sise

1
btw. teeproxy은 여기에 있습니다 : github.com/chrislusf/teeproxy
Tombart

1
또 다른 가능성은 github.com/ebowman/splitter Scala / Netty 기반입니다.
Rich K.

답변:


11

불가능하다. TCP는 statefull 프로토콜입니다. 사용자 엔드 컴퓨터는 모든 연결 단계에 관여하며 통신을 시도하는 두 개의 개별 서버에 응답하지 않습니다. 웹 서버 또는 일부 프록시에서 모든 http 요청을 수집하고 재생하기 만하면됩니다. 그러나 라이브 서버의 동시성 또는 트래픽 조건이 정확하지 않습니다.


TCP 복제는 불가능합니다. 동의합니다. 레이어 7 트래픽을 복제하는 것은 아닙니다. 클라이언트의 요청을 캡처하여 다른 서버로 재생할 수 있습니다. TCP 세션 재생 당 간단한 1 개의 요청은 매우 쉽습니다. 지속적인 연결은 클라이언트의 추가 요청 시간을 결정하는 한 약간의 생각이 필요합니다.
Evan Anderson

@Kazimieras Aliulis : 별도의 두 서버와 통신 할 필요는 없습니다. 클라이언트가 기본 서버 = 라이브 서버와 통신하고 있습니다. 라이브 서버가 클라이언트 요청을 처리하고 클라이언트에 응답하고 있습니다. 클라이언트에 대한 처리 및 응답 외에도 기본 서버는 요청을 두 번째 서버 = 테스트 서버로 복제합니다. 두 번째 서버에서 기본 서버로의 응답은 기본 서버에서 삭제 / 무시되며 클라이언트로 전달되지 않습니다.
Sise

@Evan Anderson : HTTP 수준에서의 복제 역시 우리의 첫 번째 아이디어 였지만, 예를 들어 아파치 프록시 나 유사한 툴 또는 모듈은 요청을 로컬에서 동시에 처리하고 원격 호스트에 복제하는 것을 허용하지 않습니다. 다른 아이디어가 있으면 조언하십시오! :) 우리는 즉시 비교 결과를 얻기 위해 기록 및 재생보다 복제를 선호합니다.
Sise

1
@Sise : 트래픽을 두 서버로 전달하는 고유 한 http 프록시를 작성할 수 있습니다. python Twisted framework twistedmatrix.com으로 쉽게 할 수 있습니다.
Kazimieras Aliulis

@Kazimieras Aliulis : 그것은 확실히 대안입니다! 나는 그것을 들어 본 적이 없다. 그러나 그것을 확인하면 그것이 우리의 목적에 완벽하게 부합한다는 것을 보여줍니다. 우리는 이전에 파이썬을 고려하지 않았지만 현재 우리는 일반적인 파이썬과 함께 Twisted 프레임 워크와 가능성을보고 있습니다. 성공하면 다시보고하겠습니다!
Sise

20

당신이 묘사 한 것에서, GOR은 당신의 요구에 맞는 것 같습니다. https://github.com/buger/gor/ "HTTP 트래픽은 실시간으로 재생됩니다. 프로덕션에서 스테이징 및 개발 환경에 이르는 트래픽을 재생하십시오." ?


2
이것은 정확히 내가 많이 주셔서 감사합니다 찾고 있었는지, 당신이 날 이동에, 정확히이 글을 쓰는 저장! :-)
chmac 2014

nginx에는 미러 모듈이 있습니다. nginx.org/en/docs/http/ngx_http_mirror_module.html
Jimmy MG Lim

7

Teeproxy를 사용하여 트래픽을 복제 할 수 있습니다. 사용법은 정말 간단합니다.

./teeproxy -l :80 -a localhost:9000 -b localhost:9001
  • a 생산 서버
  • b 테스트 서버

roundrobin웹 서버 앞에 HA 프록시 ( ) 를 넣으면 트래픽의 50 %를 테스트 사이트로 쉽게 리디렉션 할 수 있습니다.

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

4

@KazimierasAliulis가 지적한 것처럼 상태 저장 프로토콜 인 TCP는 단순히 다른 호스트에서 패킷의 복사본을 블라스트 처리 할 수 ​​없습니다.

TCP 종료 계층에서 패킷을 가져 와서 새로운 TCP 스트림으로 릴레이하는 것이 합리적입니다. 연결 한 복사기 도구가 최선의 방법 인 것 같습니다. TCP 프록시로 작동하여 TCP 상태 시스템이 올바르게 작동 할 수 있습니다. 테스트 머신의 응답은 폐기됩니다. 그것은 정확히 당신이 원하는 것에 대한 청구서에 맞는 것처럼 들립니다.

왜 복제기 도구를 사용할 수없는 것으로 작성했는지는 확실하지 않습니다. 도구는 단일 포트에서만 수신하기 때문에 도구의 여러 인스턴스를 실행해야하지만 아마도 다른 수신 포트 각각을 백엔드 시스템의 다른 포트로 릴레이하려고합니다. 그렇지 않은 경우 iptables DNAT를 사용하여 모든 청취 포트를 복제기 도구의 단일 청취 사본으로 지정하십시오.

테스트하는 응용 프로그램이 더럽지 않은 경우가 아니라면 타이밍 및 내부 응용 프로그램 상태와 관련된이 테스트 방법에 문제가있을 것으로 예상됩니다. 당신이하고 싶은 것은 기만적으로 간단하게 들린다. 나는 당신이 많은 최첨단 사례를 찾을 것으로 기대한다.


예, 당신은 완전히 맞습니다. agnoster duplicator 도구는 멀티 포트 상황을 제외하고 우리의 요구 사항에 맞습니다. 또한 테스트 기계의 응답 폐기가 가득 찼습니다. 실제 / 실제 상황을 최대한 정확하게 시뮬레이션한다는 목표를 달성하기 위해 라이브 서버의 모든 포트를 테스트 시스템의 단일 포트에 묶을 수 없습니다. 클라이언트 장치를 다른 고객으로 나누는 데 다른 포트가 사용됩니다. 따라서이 복제기 도구의 60-70 세션을 열어야합니다. 상상할 수 있듯이 이것은 실용적이지 않습니다.
Sise

@Sise-컴퓨터는 지루한 일을 잘합니다. Apache 구성을 구문 분석하고 60-70 개의 복제기 도구 인스턴스를 실행하는 데 필요한 명령 줄을 작성하는 스크립트를 작성할 수 있다고 생각합니다. 복사기 도구가 리소스를 많이 사용한다고 상상할 수는 없지만, 그 경우에도 다른 시스템에서 60-70 개의 인스턴스를 실행하고 트래픽을 얻기 위해 네트워크 트릭을 수행 할 수 있습니다. 적어도 나에게는 이것이 완전히 실용적이며 이것을 처리하는 매우 간단한 방법으로 보입니다.
Evan Anderson

1

그러나 비슷한 것을 시도하고 있지만 단순히 서버의 부하를 시뮬레이션하려는 경우 부하 테스트 프레임 워크와 같은 것을 볼 수 있습니다. 과거에는 locust.io를 사용했으며 서버의 부하를 시뮬레이션하는 데 실제로 효과적이었습니다. 이를 통해 많은 수의 클라이언트를 시뮬레이트 할 수 있으며 트래픽을 다른 서버로 전달하는 힘든 과정을 거치지 않고도 서버 구성을 사용할 수 있습니다.


0

"실시간 서버의 인바운드 HTTP 트래픽을 하나 이상의 원격 서버에 실시간으로 복제하려는 경우"위에서 언급하지 않은 한 가지 방법이 있는데, 스위치에 연결된 포트에 미러 포트를 구성하는 것입니다.

Cisco Catalyst 스위치의 경우이를 SPAN이라고합니다 (추가 정보는 여기 참조 ). Cisco 환경에서는 미러링 된 포트를 다른 스위치에 둘 수도 있습니다.

그러나 이것의 목적은 트래픽 분석을위한 것이므로 위의 첫 번째 단락에서 인용 된 텍스트의 단방향 키워드 인 inbound 입니다. 포트가 어떤 리턴 트래픽도 허용하지 않을 것이라고 생각합니다. 만약 그렇다면, 중복 리턴 트래픽을 어떻게 처리 하시겠습니까? 아마도 네트워크에 혼란을 줄 것입니다.

따라서 ... 목록에 하나의 가능성을 추가하고 싶었지만 실제로 단방향 트래픽에 대한 경고가 있습니다. 어쩌면 해당 미러 포트에 허브를 배치하고 시작된 세션을 선택하고 응답하는 일부 로컬 클라이언트 시뮬레이터가 중복 서버 응답을 처리 할 수 ​​있지만 들어오는 트래픽을 복제 서버로 복제 할 수 있습니다. 필요.


우리는 그것에 대해 생각했습니다 .SPAN 사용의 대안에 대해 읽었습니다. 그러나 서버는 타사 공급자의 데이터 센터에 있기 때문에 하드웨어 변경과 관련하여 가능성이 제한적입니다. 이미 두 번째 NIC에 2 대의 서버를 직접 연결하도록 요청했습니다. 이 두 서버에 대한 로컬 네트워크와 결합 된이 조치를 통해 IPTABLES를 TEE와 함께 사용할 수 있습니다. 그러나이 대안을 사용하려면 서버의 외부 IP를 변경해야합니다. 클라이언트 장치가 설정된 IP에 연결되도록 구성되어 있기 때문에 NoGo입니다.
Sise

0

Node.js와 비슷한 목적으로 리버스 프록시 /로드 밸런서를 작성했습니다 (지금은 프로덕션 준비가 아니라 재미를위한 것입니다).

https://github.com/losnir/ampel

매우 의견이 많으며 현재 다음을 지원합니다.

  • GET 라운드 로빈 선택 사용 (1 : 1)
  • POST요청 분할 사용 "마스터"및 "그림자"개념은 없습니다. 응답하는 첫 번째 백엔드는 클라이언트 요청을 처리하는 백엔드이며 다른 모든 응답은 삭제됩니다.

누군가가 유용하다고 생각하면보다 유연하게 개선 할 수 있습니다.


Node.js는 매우 높은 성능을 요구하는 이와 같은 응용 프로그램에 매우 이상한 언어 선택입니다. 이것이 생산 준비가 될지 확신하지 못합니다.
마이클 햄튼

너가 확실히 맞아. 이것은 성능이 뛰어나지 않고 작성하기 쉽습니다. 필요한 하중에 달려 있다고 생각합니다. 나는 로우 엔드 머신 (2 코어)에서 1,000rps 이상을 약간 달성 할 수있었습니다.
losnir

0

우리 회사는 비슷한 요구 사항을 가지고 패킷을 복제하고 다른 호스트로 보냅니다 (시장 데이터 시뮬레이터를 실행하고 시장 데이터 TCP 피드를 수신하고 각 패킷을 수집하지만 각 패킷의 복제본을 다른 시뮬레이터로 보내는 임시 솔루션이 필요했습니다) 섬기는 사람)

이 바이너리는 TCP Duplicator 버전으로 잘 작동하지만 jscript 대신 golang으로 작성되었으므로 더 빠르며 광고 된대로 작동합니다.

https://github.com/mkevac/goduplicator


-1

중국 회사의 한 사람이 만든 도구가 있으며 아마도 필요한 것입니다 : https://github.com/session-replay-tools/tcpcopy


2
안녕하세요. serverfault에 오신 것을 환영합니다. 더 자세한 답변을 제공해 주시겠습니까? 프로그램은 정확히 무엇을합니까? C로 작성 되었습니까?
bgtvfr
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.