我有一个MVC 5 Web应用程序在.NET 4.7.2运行,在Azure中AppService服务托管,使用Azure的主要跳马举行秘密。该项目采用Microsoft.Azure.KeyVault 3.0.3
NuGet包和秘密使用KeyVaultClient
和.GetSecretAsync()
访问。所有资源都位于同一地区天青。
在大多数情况下这工作得非常好,而对于时间约90%返回以毫秒为单位的秘密。
但每一个现在,然后调用访问密钥库失败。这本身并不表现为通过SDK抛出一个异常,但是Web应用程序挂起。最后 - 以及通常在1分钟左右,但有时更长 - 秘密返回,所有又是罚款。这是因为SDK使用重试模式,这将继续努力,让这个秘密。
综观应用的见解在AppService我可以看到,通过SDK产生的GET请求获得来自关键库中的HTTP 500响应和SocketException抛出,以ConnectFailure的结果代码。
唯一的例外是:
纵观遥测和逐步执行代码不存在共性或明显原因的元素。这似乎是完全随机的。
底线是在Azure托管应用程序服务有时无法连接到Azure的托管库的关键在同一个数据中心,采用了最新的框架和SDK版本。
有其他人看到这或有什么想法?我搜索了一圈,发现的人遇到同样的问题在少数情况,但没有人有一个原因或解决方案。
编辑(1):现在我试图在完全不同的区域旋转了一个新的密钥库,但问题仍然存在完全相同。
我们经历了我们的项目,其中KeyVault将是快速和可靠的大部分时间,然后间歇性地停止响应,或者需要很长的时间,在一段时间没有明显的理由来解释为什么一旦返回相同的行为。这发生在我们的应用程序的所有层次,从API,天青功能,命令行工具。
最后,我们必须解决这个通过缓存秘密在内存中,以避免击中KeyVault过于频繁,在那里我们的AppSettings类将在内部缓存这些。除此之外,我们还配置了DI容器对待这个类作为一个单身。
这是非常简单的例子:
public class MyAppSettings : IAppSettings
{
private readonly ObjectCache _cache = MemoryCache.Default;
private readonly object _lock = new Object();
private KeyValueClient _kvClient;
public string MySecretValue => GetSecret("MySecretValue");
private KeyValueClient GetKeyVaultClient()
{
// Initialize _kvClient if required
return _kvClient;
}
private string GetSecret(string name)
{
lock (_lock)
{
if (_cache.Contains(key))
return (string) _cache.Get(key);
// Sanitize name if required, remove reserved chars
// Construct path
var path = "...";
// Get value from KV
var kvClient = GetKeyVaultClient();
Task<SecretBundle> task = Task.Run(async() => await kvClient.GetSecretAsync(path));
var value = task.Result;
// Cache it
_cache.Set(name, value, DateTime.UtcNow.AddHours(1));
return value;
}
}
}
这不是生产做好准备 - 你需要修改这个和实施GetKeyVaultClient
方法以实际回报您KeyVaultClient对象,也是GetSecret
方法应消毒键名被检索。
在我们的DI注册表,我们有这个设置为使用一个单是这样的:
For<IAppSettings>().Use<MyAppSettings>().Singleton();
这两个变化似乎也为我们工作,我们也没有现在有任何与此问题了一会儿。