web-dev-qa-db-ja.com

TCPトラフィックをベンチマーク目的で1つまたは複数のリモートサーバーに複製する方法?

インフラストラクチャ:データセンターのサーバー、OS-Debian Squeeze、ウェブサーバー-Apache 2.2.16


状況:

ライブサーバーは私たちの顧客によって毎日使用されているため、調整や改善をテストすることは不可能です。したがって、ライブサーバー上のインバウンドHTTPトラフィックを1つまたは複数のリモートサーバーにリアルタイムで複製します。トラフィックはローカルWebサーバー(この場合はApache)とリモートサーバーに渡す必要があります。これにより、構成を調整し、ベンチマークや現在のライブサーバーとの比較のためにリモートサーバーで異なるコードや更新されたコードを使用できます。現在、ウェブサーバーは約聞いています。クライアント構造のため、80と443の他に60個の追加ポート。


質問:1つまたは複数のリモートサーバーへのこの複製をどのように実装できますか?

私たちはすでに試しました:

  • agnoster duplicator-これには、ポートごとに1つのオープンセッションが必要ですが、これは適用されません。 ( https://github.com/agnoster/duplicator
  • kklisプロキシ-トラフィックをリモートサーバーに転送するだけで、lcoalウェブサーバーに渡しません。 ( https://github.com/kklis/proxy
  • iptables-DNATはトラフィックを転送するだけで、ローカルのWebサーバーには渡さない
  • iptables-TEEはローカルネットワーク内のサーバーにのみ複製します->データセンターの構造により、サーバーは同じネットワークに配置されていません
  • stackoverflow( https://stackoverflow.com/questions/7247668/duplicate-tcp-traffic-with-a-proxy )で質問「プロキシを使用したtcpトラフィックの重複」に対して提供された代替案は失敗しました。前述のとおり、TEEはローカルネットワーク外のリモートサーバーでは機能しません。 teeproxyは使用できなくなり( https://github.com/chrislusf/tee-proxy )、他の場所では見つかりませんでした。
  • 2番目のIPアドレス(同じネットワークにある)を追加し、それをeth0:0に割り当てました(プライマリIPアドレスはeth0に割り当てられています)。この新しいIPまたは仮想インターフェースeth0:0をiptables TEE関数またはルートと組み合わせても成功しません。
  • 「debian squeezeでの重複する着信tcpトラフィック」( 重複する着信TCP Debian Squeezeでのトラフィック )の質問に対して提供された代替案は失敗しました。cat| ncセッション(cat/tmp/prodpipe | nc 127.0.0.1 12345およびcat/tmp/testpipe | nc 127.0.0.1 23456)は、クライアントからのすべての要求/接続の後に通知やログなしに中断されます。キープアライブはこの状況を変更しませんでした。TCPパッケージはリモートシステムに転送されませんでした。
  • Socat(HowTo: http://www.cyberciti.biz/faq/linux-unix-tcp-port-forwarding/https:// stackoverflow .com/questions/9024227/duplicate-input-unix-stream-to-multiple-tcp-clients-using-socat )および同様のツールは、提供されたTEE関数がFSのみ。
  • もちろん、この「問題」または設定をググって検索することもできませんでした。

ここではオプションが不足しています。

IPTABLESを使用するときにTEE機能の「ローカルネットワーク内のサーバー」の適用を無効にする方法はありますか?

IPTABLESまたはルートのさまざまな使用法によって目標を達成できますか?

この目的のためにテストされ、これらの特定の状況で機能する別のツールを知っていますか?

Tプロキシの別のソースはありますか(これは、AFAIKの要件に完全に適合します)?


返信ありがとうございます。

----------

編集: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:宛先サーバーのリモートポート
および戻り設定

33
Sise

それは無理だ。 TCPはステートフルプロトコルです。ユーザーエンドコンピューターは接続のすべてのステップに関与しており、通信を試みる2つの個別のサーバーに応答することはありません。Webサーバー上のすべてのhttp要求を収集するだけです。またはいくつかのプロキシとそれらを再生しますが、ライブサーバーの同時実行性またはトラフィック状態を正確に提供しません。

11

あなたの説明から、GORはあなたのニーズに合っているようです。 https://github.com/buger/gor/ 「HTTPトラフィックをリアルタイムで再生します。本番環境からステージング環境および開発環境へのトラフィックを再生します。」 ?

20
Arthur Lutz

Teeproxy を使用してトラフィックを複製できます。使い方は本当に簡単です:

./teeproxy -l :80 -a localhost:9000 -b localhost:9001
  • a本番サーバー
  • bテストサーバー

Webサーバーの前にHAproxy(roundrobin付き)を配置すると、トラフィックの50%をテストサイトに簡単にリダイレクトできます。

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

ステートフルプロトコルであるTCPは、@ KazimierasAliulisが指摘しているように、別のホストでパケットのコピーをブラストするだけでは対応できません。

TCPターミネーションの層でパケットを取得し、それらを新しいものとしてリレーするTCPストリームは妥当です。 複製ツール あなたにリンクされているように見えます。これはTCPプロキシとして動作し、TCPステートマシンが適切に動作できるようにします。テストマシンからの応答は、それはまさにあなたが欲しいものの法案に合うように聞こえます。

なぜあなたがデュプリケーターツールを受け入れられないものとして書いたのか、私にははっきりしません。ツールは単一のポートでのみリッスンするため、ツールの複数のインスタンスを実行する必要がありますが、おそらく、これらの異なるリッスンポートのそれぞれをバックエンドシステムの異なるポートにリレーする必要があります。そうでない場合は、iptables DNATを使用して、すべてのリスニングポートをデュプリケータツールの単一のリスニングコピーに転送できます。

テストするアプリケーションが単純なものでない限り、タイミングと内部アプリケーションの状態に関連するこのテスト方法論に問題が発生すると思います。あなたがしたいことは一見単純そうに聞こえます-私はあなたが多くのEdgeケースを見つけることになると思います。

4
Evan Anderson

私は同様のことをしようとしていますが、単にサーバーの負荷をシミュレートしようとしているのであれば、負荷テストフレームワークのようなものを検討します。私は過去にlocust.ioを使用しましたが、サーバーの負荷をシミュレートするのに非常によく機能しました。これにより、多数のクライアントをシミュレートして、別のサーバーにトラフィックを転送するという面倒なプロセスを実行しなくても、サーバーの構成を試すことができます。

1
snowbirdSkiBum

私の会社にも同様の要件があり、パケットを複製して別のホストに送信しました(市場データシミュレーターを実行し、市場データをリッスンする一時的なソリューションが必要でしたTCPフィード、各パケットを取り込みますが、各パケットのクローンを別のシミュレータサーバーに送信する)

このバイナリは非常にうまく動作し、TCP Duplicatorのバージョンですが、jscriptではなくgolangで記述されているため、高速であり、宣伝どおりに機能します。

https://github.com/mkevac/goduplicator

0
perfecto25

「ライブサーバーのインバウンドHTTPトラフィックを1つまたは複数のリモートサーバーにリアルタイムで複製したい」という限り、上記に記載されていない1つの方法があります。それは、接続先のスイッチにミラーポートを構成することです。

Cisco Catalystスイッチの場合、これはSPANと呼ばれます(詳細 こちら )。シスコ環境では、ミラーリングされたポートを別のスイッチに配置することもできます。

しかし、これの目的はトラフィック分析であるため、単方向になります-上記の最初の段落の引用テキスト内のキーワード:inbound。このポートでリターントラフィックが許可されるとは思いません。許可すると、重複するリターントラフィックにどのように対処しますか?それはおそらくあなたのネットワークに大混乱をもたらすでしょう。

つまり、リストに1つの可能性を追加したいだけですが、実際には一方通行のトラフィックになる可能性があるという警告があります。多分あなたはそのミラーポートにハブを置くことができ、開始されたセッションをピックアップして応答するローカルクライアントシミュレーターによって複製されたサーバー応答を渡すことができますが、その場合、あなたの複製サーバーへの着信トラフィックを複製するでしょう...欲しいです。

0
James

Node.jsを使用して、同様の目的でリバースプロキシ/ロードバランサーも作成しました(現時点では面白くするためのものであり、現時点では本番環境に対応していません)。

https://github.com/losnir/ampel

それは非常に独断的であり、現在サポートしています:

  • GETラウンドロビン選択の使用(1:1)
  • POSTリクエスト分割を使用します。 「マスター」と「シャドウ」の概念はありません-応答する最初のバックエンドはクライアント要求を処理するものであり、その後、他のすべての応答は破棄されます。

誰かがそれが便利だと思ったら、私はそれをより柔軟に改善することができます。

0
losnir