我正在开发一个相当复杂的Xamarin.Forms应用程序。我们提出了很多REST请求。据报道,我们的应用程序没有及时支持DNS故障转移以实现负载平衡,所以我开始调查。我正在运行dnsmasq,这样我就可以查看应用程序何时发出DNS请求。这段代码目前使用的是HttpWebRequest
,我注意到它的查询间隔至少为10分钟。
我理解这一点的部分原因是因为大多数.NET网络部分都使用保持连接。如果我强制报头不使用keepalive,我肯定会看到更高的DNS查询率,但这会增加网络开销,所以这不是一个理想的解决方案。但我最初并没有看到一种清晰的方法来控制HttpWebRequest
如何进行DNS查询。
我可以获得它的ServicePoint
属性并在其上设置ConnectionLeaseTimeout
,这看起来很有希望。不幸的是,这在Xamarin中抛出了NotImplementedException
,所以它不会成为任何解决方案的一部分。
我想也许HttpClient
会更具可配置性。我看到很多关于如何正确使用它的讨论,如果你这样做,你需要为你希望ServicePointManager.DnsRefreshTimeout
频繁更新的用例设置一个较小的值。但这通常是与获取deisred端点的ServicePoint
和修改ConnectionLeaseTimeout
一起完成的,这是不可能的。
我一直在用一个非常简单的应用程序进行测试,它重用了一个HttpClient,并在我按下按钮时发出相同的请求。用一个按钮把这个ViewModel放在一些Xaml后面:
using System;
using Xamarin.Forms;
using System.Net.Http;
using System.Net;
namespace TestDns {
public class MainPageViewModel {
private const string _URL = "http://www.example.com";
private HttpClient _httpClient;
private ServicePoint _sp;
public MainPageViewModel() {
var sp = ServicePointManager.FindServicePoint(new Uri(_URL));
_sp = sp;
//_sp.ConnectionLeaseTimeout = 100; // throws NIE
_httpClient = new HttpClient();
ServicePointManager.DnsRefreshTimeout = 100;
}
public Command WhenButtonIsClicked {
get {
return new Command(() => SendRequest());
}
}
private async void SendRequest() {
Console.WriteLine($"{_sp.CurrentConnections}");
var url = "http://www.example.com";
var response = await _httpClient.GetAsync(url);
Console.WriteLine($"{response.Content}");
}
}
}
我没想到ConnectionLeaseTimeout
会抛出。我希望这段代码只能缓存100ms的DNS请求,我打算在更多面向生产的测试中选择一个更合理的时间框架,比如2-3分钟。但是由于我不能让这个简单的例子像我想要的那样工作,所以增加延迟似乎没有意义。
肯定有人在Xamarin应用程序中遇到过这个问题?我唯一的解决方案是深入研究并尝试使用本机网络构造吗?
发布于 2018-06-23 03:15:49
如果你在Android上这样做,DNS会被缓存10分钟,我不相信你有任何从你的应用程序内部访问到期/刷新时间的权限。有许多方法可以强制刷新,但它们都涉及用户操作,如进入网络连接并从静态切换到DHCP和返回等。
我能想到的确保从你的应用程序内部获得新的DNS查找的唯一方法是让10+分钟的DNS条目包含所有别名到你的服务器,并循环通过它们,所以每次你请求DNS查找时,它都是一个新名称,而不是在缓存中。
例如,查找1.server.example.com 2.server.example.com等。每个新名称都将强制执行新的查找,并且不会从缓存中取出,因为它不在那里。
发布于 2018-06-28 23:08:26
似乎Java已经决定了“一些人不正确地实现DNS而忽略TTL”的解决方案是通过确保使用Java的设备不正确地实现DNS来使问题变得更糟。缓存中的所有DNS条目都使用一个TTL。有一些哲学上的争论,以及是什么让我在this question中找到了答案,我将其改编为答案。
在Xamarin项目方面,在某个地方添加以下内容(我在MainActivity早期选择了它):
Java.Security.Security.SetProperty("networkaddress.cache.ttl", "<integer seconds>");
将所有DNS条目的"“替换为所需的TTL。注意,较低的值可能意味着您进行了比以前更多的DNS查询,如果您认真地尝试节省网络字节,这可能是一个问题。
我把Terry Carmen的答案选为“答案”。
https://stackoverflow.com/questions/50994072
复制相似问题