自托管owin Webapi导致的奇怪崩溃

时间:2019-07-11 06:44:18

标签: c# .net owin

我有一个控制台应用程序,它自己托管一个将pdf转换为pdfa的owin webapi和另一个调用该webapi的控制台应用程序。

问题有点奇怪。我可以用一个大小为33KB的文件连续两次调用webapi,但是如果我用2.6mb的文件调用两次,那么从服务器的角度来看,它两次都返回转换后的文件数据,但是第二次是在服务器硬退出而不报告错误之前短暂的延迟,而客户端报告以下嵌套的异常。

1. "HttpRequestException: Error while copying content to a stream."
2. "Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host"
3. "An existing connection was forcibly closed by the remote host" 

现在输入服务器端代码

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        // Configure Web API for self-host. 
        HttpConfiguration config = new HttpConfiguration();
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        app.UseCors(CorsOptions.AllowAll);
        app.UseWebApi(config);

        JsonConvert.DefaultSettings = () => new JsonSerializerSettings
        {
            NullValueHandling = NullValueHandling.Ignore,
            Formatting = Formatting.None,
        };
    }
}

然后使用以下命令启动自托管服务器

WebApp.Start<Startup>(url);

控制器

public class ConvertPdfByteArrayToPdfaController : ApiController
{
    public ConvertPdfByteArrayToPdfaResponse Post([FromBody]ConvertPdfByteArrayToPdfaRequest request)
    {
        try
        {                    
            //lots of work here

            jsonLight = result.GetJsonLight();
            return result;
        }
        catch (Exception ex)
        {
            throw logger.LogExceptionForReThrow("There was a problem trying to convert the PDF to PDFa", ex);
        }
        finally
        {    
            logger.End("Returned", $"Returned: {jsonLight}");
        }
    }
}

这可以很好地完成两次返回和记录器的成功。

现在是客户端

private HttpClient GetWebApiPdfClient(string serverHostName, int portNumber)
{
    var client = new HttpClient();
    client.BaseAddress = new Uri($"http://{serverHostName}:{portNumber}/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json"));
    client.Timeout = TimeSpan.FromHours(2);
    client.MaxResponseContentBufferSize = 1000000000;
    return client;
}


public ConvertPdfByteArrayToPdfaResponse ConvertPdfByteArrayToPdfa(byte[] byteArray, bool certify)
{
    var request = new ConvertPdfByteArrayToPdfaRequest { PdfByteArray = byteArray, Certify = certify };
    return PostObject<ConvertPdfByteArrayToPdfaResponse>("api/convertPdfByteArrayToPdfa", request);
}

private T PostObject<T>(string endpoint, object data)
{
    using (var client = GetWebApiPdfClient())
    {
        var json = JsonConvert.SerializeObject(data);
        var content = new StringContent(json, Encoding.UTF8, "application/json");

        var response = client.PostAsync(endpoint, content).Result;  //Fails the second time here on a 2.6mb file but works fine for first file 2.6mb file
        var responseText = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

        if (response.StatusCode != HttpStatusCode.OK)
            throw new Exception($"Expected returnCode:{HttpStatusCode.OK} but received {response.StatusCode}");
        if (response.Content.Headers.ContentLength > 0)
            return JsonConvert.DeserializeObject<T>(responseText);

        throw new Exception($"response content length was 0");
    }
}

呼叫代码

            var webApiPdfClient = new WebApiPdfClient();
            var response = webApiPdfClient.ConvertPdfByteArrayToPdfa(pdfOriginalFile.ReadAllBytes(), false);
            file1.WriteAllBytes(response.PdfaByteArray);
            var response2 = webApiPdfClient.ConvertPdfByteArrayToPdfa(pdfOriginalFile.ReadAllBytes(), false);
            file2.WriteAllBytes(response2.PdfaByteArray);

服务器硬崩溃时会创建两个Windows事件日志 第一次错误事件日志条目

Faulting application name: xxxxxxxxService.exe, version: 1.0.0.0, time stamp: 0x94123e39
Faulting module name: ucrtbase.dll, version: 10.0.17134.677, time stamp: 0x9f346d3f
Exception code: 0xc0000409
Fault offset: 0x000000000006e14e
Faulting process ID: 0x4f7c
Faulting application start time: 0x01d537b0b4116e7c
Faulting application path: C:\xxxxxxxxService.exe
Faulting module path: C:\WINDOWS\System32\ucrtbase.dll
Report ID: a32399dd-a1d3-4493-9f6c-ef6cb45453e4
Faulting package full name: 
Faulting package-relative application ID: 

第二信息事件日志条目

Fault bucket 1930686170833522916, type 5
Event Name: BEX64
Response: Not available
Cab Id: 0

Problem signature:
P1: xxxxxxxxService.exe
P2: 1.0.0.0
P3: 94123e39
P4: ucrtbase.dll
P5: 10.0.17134.677
P6: 9f346d3f
P7: 000000000006e14e
P8: c0000409
P9: 0000000000000007
P10: 

Attached files:
\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WER1B21.tmp.mdmp
\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WER1D93.tmp.WERInternalMetadata.xml
\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WER1DA4.tmp.xml
\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WER1DB2.tmp.csv
\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WER1DD2.tmp.txt

These files may be available here:
C:\ProgramData\Microsoft\Windows\WER\ReportArchive\AppCrash_xxxxxxxx_c7be53f830b5ebee58beaeda68b8ea707ef39a54_6dd26e0f_1fb623ad

Analysis symbol: 
Rechecking for solution: 0
Report Id: a32399dd-a1d3-4493-9f6c-ef6cb45453e4
Report Status: 268435456
Hashed bucket: fd129a9a61ef2bd3facb2cd7d94a90e4
Cab Guid: 0

我只是不确定这次硬崩溃的原因是什么。

1 个答案:

答案 0 :(得分:0)

该问题是由我没有处理的第三方库引起的。该库的试用版未引起问题,但许可版本引起了该问题。由于是半间歇性的和严重的崩溃,因此很难定位。但是当我缩小它的范围时,似乎垃圾收集器正在与它发生冲突。