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

인프라 : 데이터 센터 서버, 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 : 대상 서버의 원격 포트
및 리턴 설정



답변

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


답변

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


답변

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

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

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

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


답변

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

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

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

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


답변

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


답변

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

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

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

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


답변

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

https://github.com/losnir/ampel

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

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

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