我在 Azure ML 中创建了一个简单的实验,并使用 http 客户端触发它。在 Azure ML 工作区中,执行时一切正常。但是,当我使用 http 客户端触发实验时,实验会超时并失败。为 http 客户端设置超时值似乎不起作用。
我们有什么办法可以设置这个超时值,这样实验就不会失败?
我在 Azure ML 中创建了一个简单的实验,并使用 http 客户端触发它。在 Azure ML 工作区中,执行时一切正常。但是,当我使用 http 客户端触发实验时,实验会超时并失败。为 http 客户端设置超时值似乎不起作用。
我们有什么办法可以设置这个超时值,这样实验就不会失败?
确保正确设置客户端超时值。如果为 Web 服务供电的服务器超时,那么它将返回带有 HTTP 状态代码504 BackendScoreTimeout
(或可能409 GatewayTimeout
)的响应。但是,如果您根本没有收到响应,那么您的客户等待的时间不够长。
您可以通过在 ML Studio 中运行实验来找出大量时间。转到实验属性以了解它运行了多长时间,然后将大约两倍的时间作为超时值。
我在作为 Web 服务发布的 Azure ML 实验中遇到了类似的问题。大多数时候它运行正常,而有时它返回超时错误。问题是实验本身有90 秒的运行时间限制。因此,很可能您的实验的运行时间超过了此限制并返回超时错误。hth
似乎无法根据截至 2018 年 4 月 1 日仍标记为“已计划”的功能请求设置此超时。
2017 年 MSDN 论坛的推荐是使用 Batch Execution Service,它启动机器学习实验,然后异步询问是否完成。
这是 Azure ML Web 服务管理示例代码中的代码片段(所有注释均来自其示例代码):
using (HttpClient client = new HttpClient())
{
var request = new BatchExecutionRequest()
{
Outputs = new Dictionary<string, AzureBlobDataReference> () {
{
"output",
new AzureBlobDataReference()
{
ConnectionString = storageConnectionString,
RelativeLocation = string.Format("{0}/outputresults.file_extension", StorageContainerName) /*Replace this with the location you would like to use for your output file, and valid file extension (usually .csv for scoring results, or .ilearner for trained models)*/
}
},
},
GlobalParameters = new Dictionary<string, string>() {
}
};
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
// WARNING: The 'await' statement below can result in a deadlock
// if you are calling this code from the UI thread of an ASP.Net application.
// One way to address this would be to call ConfigureAwait(false)
// so that the execution does not attempt to resume on the original context.
// For instance, replace code such as:
// result = await DoSomeTask()
// with the following:
// result = await DoSomeTask().ConfigureAwait(false)
Console.WriteLine("Submitting the job...");
// submit the job
var response = await client.PostAsJsonAsync(BaseUrl + "?api-version=2.0", request);
if (!response.IsSuccessStatusCode)
{
await WriteFailedResponse(response);
return;
}
string jobId = await response.Content.ReadAsAsync<string>();
Console.WriteLine(string.Format("Job ID: {0}", jobId));
// start the job
Console.WriteLine("Starting the job...");
response = await client.PostAsync(BaseUrl + "/" + jobId + "/start?api-version=2.0", null);
if (!response.IsSuccessStatusCode)
{
await WriteFailedResponse(response);
return;
}
string jobLocation = BaseUrl + "/" + jobId + "?api-version=2.0";
Stopwatch watch = Stopwatch.StartNew();
bool done = false;
while (!done)
{
Console.WriteLine("Checking the job status...");
response = await client.GetAsync(jobLocation);
if (!response.IsSuccessStatusCode)
{
await WriteFailedResponse(response);
return;
}
BatchScoreStatus status = await response.Content.ReadAsAsync<BatchScoreStatus>();
if (watch.ElapsedMilliseconds > TimeOutInMilliseconds)
{
done = true;
Console.WriteLine(string.Format("Timed out. Deleting job {0} ...", jobId));
await client.DeleteAsync(jobLocation);
}
switch (status.StatusCode) {
case BatchScoreStatusCode.NotStarted:
Console.WriteLine(string.Format("Job {0} not yet started...", jobId));
break;
case BatchScoreStatusCode.Running:
Console.WriteLine(string.Format("Job {0} running...", jobId));
break;
case BatchScoreStatusCode.Failed:
Console.WriteLine(string.Format("Job {0} failed!", jobId));
Console.WriteLine(string.Format("Error details: {0}", status.Details));
done = true;
break;
case BatchScoreStatusCode.Cancelled:
Console.WriteLine(string.Format("Job {0} cancelled!", jobId));
done = true;
break;
case BatchScoreStatusCode.Finished:
done = true;
Console.WriteLine(string.Format("Job {0} finished!", jobId));
ProcessResults(status);
break;
}
if (!done) {
Thread.Sleep(1000); // Wait one second
}
}
}