私はバックエンドサーバに接続されたシンプルなTCPフォワーダを実装しました。このサーバーはhttp://localhost:5000
に設定されており、このTCPフォワーダはhttp://localhost:5001
を受信しています。 wrk
which is a HTTP benchmarking tool to generator loadを使用して別のマシンを使用して負荷を生成すると、2つの異なる結果が生じます。 kestrel
のasp.net core web api
に基づくサービスに負荷を直接送信すると、230Kリクエスト/秒以上が処理されますが、このTCPフォワーダに負荷を送信すると、83Krequest /秒を処理できます。コードは次のとおりです。Cでソケットを使用してTCPフォワーダを改善する#
using System;
using System.Net;
using System.Net.Sockets;
namespace BrunoGarcia.Net
{
static void Main(string[] args)
{
new TcpForwarderSlim().Start(
new IPEndPoint(IPAddress.Parse(args[0]), int.Parse(args[1])),
new IPEndPoint(IPAddress.Parse(args[2]), int.Parse(args[3])));
}
public class TcpForwarderSlim
{
private readonly Socket _mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public void Start(IPEndPoint local, IPEndPoint remote)
{
_mainSocket.Bind(local);
_mainSocket.Listen(10);
while (true)
{
var source = _mainSocket.Accept();
var destination = new TcpForwarderSlim();
var state = new State(source, destination._mainSocket);
destination.Connect(remote, source);
source.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, OnDataReceive, state);
}
}
private void Connect(EndPoint remoteEndpoint, Socket destination)
{
var state = new State(_mainSocket, destination);
_mainSocket.Connect(remoteEndpoint);
_mainSocket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, OnDataReceive, state);
}
private static void OnDataReceive(IAsyncResult result)
{
var state = (State)result.AsyncState;
try
{
var bytesRead = state.SourceSocket.EndReceive(result);
if (bytesRead > 0)
{
state.DestinationSocket.Send(state.Buffer, bytesRead, SocketFlags.None);
state.SourceSocket.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, OnDataReceive, state);
}
}
catch
{
state.DestinationSocket.Close();
state.SourceSocket.Close();
}
}
private class State
{
public Socket SourceSocket { get; private set; }
public Socket DestinationSocket { get; private set; }
public byte[] Buffer { get; private set; }
public State(Socket source, Socket destination)
{
SourceSocket = source;
DestinationSocket = destination;
Buffer = new byte[8192];
}
}
}
}
問題は何ですか? TCPフォワーダを使用すると、結果をどのように改善できますか?または、ポートをリッスンして2つ以上のバックエンドサービスの1つにTCPリクエストを送信するためのトンネルまたはフォワーダを作成するより良い方法はありますか。
ありがとうございますが、このソリューションはrpsを10Kに完全にダウングレードしました。 :| – Alex
それは価値があった。この種のソリューションを最適化するより良い方法があるかもしれません。私は2つのバージョンでプロファイラを使用し、両方のホットスポットがどこにあるかを見ていきます。また、このソリューションをより大きなバッファー・サイズまたはより小さなバッファー・サイズで試してください。私は自分の 'Math.Min(SourceSocket.ReceiveBufferSize、DestinationSocket.SendBufferSize); 'が助けになると思ったが、おそらくパフォーマンスを傷つけるだろう。 –