我们使用SharpSVN以编程方式访问SVN存储库。现在我们遇到的问题是,通过svn://或http:// urls访问本地存储库非常慢 - 每次访问都需要至少一秒,而我们的应用程序需要获取一堆属性和目录列表。
我们可以在两台不同的机器上重现这个问题,它们都是Windows 7 32位并且位于同一个域中。 SVN服务器是http:// urls的VisualSVN 2.1.9和svn:// urls的CollabNet 1.6.17。通过“localhost”和主机名显示连接。它出现在我们的C#应用程序中,以及使用IronPython和调用SharpSvn svn.exe命令的小型测试平台应用程序。
访问远程存储库(Linux和Windows XP服务器)时访问时不会发生此问题 - 此处,每次访问时间介于0.01和0.08秒之间,这是由于网络延迟所致。通过file:// urls访问本地存储库或通过CollabNet中的“native”svn命令行工具访问存储库时,也不会发生此问题。
现在我的问题是:Windows 7或.NET或SharpSVN是否有一些仅适用于localhost连接的内置限制?
(另外:我现在发现,当使用System.Net.Sockets.TcpClient通过小型C#测试程序连接时,此限制也适用:
服务器:
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));
}
}
}
所以这个问题似乎不是特定于颠覆的。)
Addition2:在Windows的Mono 2.10下运行客户端时,问题不会出现。所以它似乎特定于.NET框架。
补充3:这似乎是与IPv6相关的问题。服务器仅侦听IPv4,但主机名也解析为IPv6。现在似乎OS代码在内部尝试IPv6连接,并在获得连接重置后,等待1秒后再回退到IPv4。每次连接尝试都会重复此游戏。 http://msdn.microsoft.com/en-us/library/115ytk56.aspx记录了TcpClient的内容(感谢MSDN论坛中的Andreas Johansson提示!),似乎Apache内部使用的APR使用了类似的机制。
答案 0 :(得分:2)
添加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 Webserver也可以这样做:
Listen 0.0.0.0:80
Listen [::]:80