SharpSVN лимит скорости соединения с localhost? - PullRequest
1 голос
/ 13 июля 2011

Мы используем SharpSVN для программного доступа к репозиториям SVN.Теперь у нас проблема в том, что доступ к локальным репозиториям через svn: // или http: // urls очень медленный - каждому доступу требуется по крайней мере одна секунда, а нашему приложению нужно получить набор свойств и списков каталогов.

Мы могли бы воспроизвести проблему на двух разных машинах, оба являются 32-разрядными Windows 7 и находятся в одном домене.SVN-серверами являются VisualSVN 2.1.9 для http: // urls и CollabNet 1.6.17 для svn: // urls.Он появляется для соединений через "localhost" и через имя хоста.Он появляется в нашем приложении C #, а также в небольшом тестовом приложении с использованием IronPython и при вызове команды SharpSvn svn.exe.

Эта проблема не возникает при доступе к удаленным репозиториям (как в Linux, так и в WindowsXP server) - здесь каждый доступ составляет от 0,01 до 0,08 с, что ожидается из-за задержки в сети.Проблема также не возникает при доступе к локальным репозиториям через file: // urls или при доступе к репозиториям через "нативные" инструменты командной строки svn из CollabNet.

Теперь мой вопрос: есть ли Windows 7 или .NETили SharpSVN какой-то встроенный лимит, который применяется только к локальным соединениям?

(Дополнение: теперь я обнаружил, что этот лимит также применяется при подключении с помощью небольшой тестовой программы на C # с использованием System.Net.Sockets.TcpClient:

Сервер:

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;

namespace TcpSpeedServer
{
    class Program
    {
        public static void Main()
        {
            Int32 port = 47011;
            IPAddress localAddr = IPAddress.Parse("127.0.0.1");

            var server = new TcpListener(localAddr, port);
            server.Start();

            Console.WriteLine("Listening on {0} : {1}", localAddr, port);

            ulong count = 0;
            // Enter the listening loop.
            while(true)
            {
                using (var client = server.AcceptTcpClient()) {
                    Console.WriteLine("Connected: {0} {1}!", count, client.Client.RemoteEndPoint);
                    count += 1;

                    using (var stream = client.GetStream()) {
                        using (StreamWriter writer = new StreamWriter(stream))
                            using (StreamReader reader = new StreamReader(stream))
                        {
                            string query = reader.ReadLine();
                            writer.WriteLine("GET / HTTP/1.0");
                            writer.WriteLine();
                            writer.Flush();
                        }
                    }
                }
            }
        }
    }
}

Клиент:

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Threading;

namespace TcpSpeedTest
{
    class Program
    {
        const bool ASYNC = false;
        static DateTime s_now;
        public static void Main(string[] args)
        {
            var liste = new List<object>();
            s_now = DateTime.Now;
            for (int i=0; i < 100; i += 1) {
                if (ASYNC)
                    ThreadPool.QueueUserWorkItem(connect, i);               
                else
                    connect(i);
            }

            Console.WriteLine("outer: " + (DateTime.Now - s_now));
            Console.ReadLine();
        }

        private static void connect(object i)
        {
            DateTime now = DateTime.Now;

            using (TcpClient client = new TcpClient("localhost", 47011))
            {
                var stream = client.GetStream();
                using (StreamWriter writer = new StreamWriter(stream))
                    using (StreamReader reader = new StreamReader(stream))
                {
                    writer.WriteLine("GET / HTTP/1.0");
                    writer.WriteLine();
                    writer.Flush();
                    string result = reader.ReadLine();
                }
            }
            Console.WriteLine(string.Format("inner: {0} - {1} - {2}", i, DateTime.Now - now, DateTime.Now - s_now));
        }
    }
}

Таким образом, эта проблема, по-видимому, не относится к subversion.)

Добавление 2: При запуске клиентапод Mono 2.10 для windows проблема не появляется.Похоже, что это специфично для .NET Framework.

Добавление 3: Кажется, это проблема, связанная с IPv6.Сервер только прослушивает IPv4, но имя хоста также преобразуется в IPv6.Теперь кажется, что код ОС внутренне пытается установить соединение IPv6 и после сброса соединения ждет 1 секунду, прежде чем вернуться к IPv4.И эта игра повторяется для каждой попытки подключения.http://msdn.microsoft.com/en-us/library/115ytk56.aspx документирует это для TcpClient (спасибо Андреасу Йоханссону из форумов MSDN за подсказку!), И кажется, что APR, используемый Apache внутри, использует аналогичный механизм.

1 Ответ

2 голосов
/ 16 июля 2011

Дополнение 3 также является решением вашей проблемы.Чтобы это исправить, либо разрешите файлу DNS / hosts разрешать только IPv4-адрес, либо заставьте серверы IPv6 работать.

Вы можете ввести в C:\Windows\System32\drivers\etc\hosts что-то вроде:

127.0.0.1 localhost-ipv4

А затем используйте это имя для подключения.

Вы также можете заставить svnserve прослушивать адреса IPv6.Быстрый поиск параметров svnserve [показал] [1], что по умолчанию используется IPv6, поэтому в его параметрах запуска, вероятно, --listen-host.Попробуйте удалить его или, когда его нет, принудительно запустить его на IPv6.

То же самое можно сделать для веб-сервера Apache:

Listen 0.0.0.0:80
Listen [::]:80
...