2017-11-01 7 views
-2

Azure App 서비스에 배포 된 AspNetCore에 WebApi가 있습니다. WebApi는 객체 배열을 게시하는 데에만 사용할 수 있습니다. 객체에는 많은 속성 (100 개 이상)과 3 개의 객체 배열이 포함됩니다. (그것은 건물을 나타냅니다). 객체 배열에는 각각 300 개가 넘는 객체가 포함될 수 있습니다.대규모 요청시 Azure 연결 설정의 웹 API가 실패 함

Visual Studio 2017 (15.4.1)에서 디버깅 할 때 api가 제대로 작동하고 모든 요청을 수락합니다. Azure에 배포하면 대부분의 요청을 받아들입니다. 그러나 몇몇은 무효로 사라집니다. 그 말은 응답이 전혀 없다는 의미입니다. 잘못 된 요청에는 배열 중 하나에 많은 객체가 있습니다. 오브젝트의 양을 특정 숫자로 줄이면 요청이 승인됩니다. 마찬가지로 Visual Studio에서는 모든 요청이 수락됩니다. 데이터 전송은 견고합니다.

나는 인터페이스가 동일하지만 로직이없고 테스트 응답을 "succes"로 만들었습니다! 이 인터페이스에서 요청도 실패합니다 (동일한 동작). Newtonsoft (10.0.3)는 비 직렬화를 위해 두 컨트롤러에서 사용됩니다.

이러한 요청에 따라 이러한 동작의 차이가 발생할 수있는 원인은 무엇입니까?

컨트롤러의 코드 :

public class TestController : Controller 
{  
    [HttpPost] 
    [RequireHttps] 
    public IActionResult Post([FromBody] Buildings Buildings) 
    { 
     enumActionResult status = enumActionResult.success; 
     try 
     { 
      if (Buildings == null) 
       throw new Exception("No valid buildings posted!"); 

      if (Buildings.items == null) 
       throw new Exception("No valid building items posted!"); 

      if (Buildings.items.Count == 0) 
       throw new Exception("Zero building items posted!"); 


      return Json(new response() { status = status.ToString(), Buildings = list 
     } 

     catch (Exception ex) 
     { 
      return Json(new ErrorResponseFormat() { message = ex.Message, status = enumActionResult.error, data = new ErrorResponse(ex) }); 
     } 
    } 
} 

업데이트 (2017년 12월 19일) : 문제는 여전히 존재하지만, SSL로 좁혀된다. 나는 실패 URL에 HTTPS와 요청을하고, 나는 그것이 succesfull 인 HTTP의 URL에 동일한 요청을 발사하면

public class EchoController : Controller 
    { 
     [HttpPost]   
     public IActionResult Post() 
     { 
      return new FileStreamResult(Request.Body, Request.ContentType); 
     } 
    } 

: 난 단지 요청을 반환하는 새로운 컨트롤러를 만들었습니다. 이것은 http 만 사용하기 때문에 디버거에서 얻은 것과 동일한 동작입니다. 따라서 디버거와 하늘 구름 환경 사이의 차이점 대신 http와 https가 문제가되는 것 같습니다. (브루스 첸에 의해 제안) 내가 설정에서 구현 한편

:

<system.webServer> 
     <security> 
      <requestFiltering> 
      <!-- Measured in Bytes --> 
      <requestLimits maxAllowedContentLength="4000000000" maxQueryString="100000000"/>   
      <!-- 1 GB, Byte in size, up to 2GB--> 
      </requestFiltering> 
     <access sslFlags="Ssl, SslRequireCert"/>   
     </security> 
     </system.webServer> 

및 .NET 4.6.2로 업그레이드. 이 시점에서 여전히 해결책은 없지만 문제는 좁혀진 것처럼 보입니다.

업데이트 (20-12-2017)은 : 나는 다음과 같은 흥미로운 점을 발견 : 나는 분실 된 (HTTPS) API에 "대형"요청을 보낼 때. 그러나 작은 요청이 선행 될 때 두 요청이 모두 허용됩니다. 따라서 큰 요청이있는 연결 설정이 실패한 것처럼 보입니다.

webapi는 사용자 정의 도메인 https 및 IP 허용 목록을 사용합니다. 클라이언트는 클라이언트 인증서로 인증해야합니다. 전체 Webapi의 설정 (예, 이전에 requestLimits 항목을 제거) :

configuration> 
    <connectionStrings> 
    ... 
    </connectionStrings> 
    <system.webServer> 
    <security>  
     <access sslFlags="Ssl, SslRequireCert"/> 
    </security> 
    </system.webServer> 
    <runtime> 
     <gcServer enabled="true"/> 
    </runtime> 
</configuration> 

그리고 클라이언트 인증서를 사용하여, 우체부이다. 이견있는 사람?

+1

우리는 몇 가지 코드 또는 로그 또는 뭔가를 보거나 그냥 추측 할 것입니다 ... – Milney

+0

여기에 아무도 어떤 코드를 게시 할 필요가있는 심령술사가 없습니다. 잠재적으로 잘리는 POST 요청 및 GET이 아닌지 확인하고 있습니까? 당신은 newsoft가 deserialization에 사용되는 것을 의미합니까? 사용자 정의 모델 바인더를 가지고 있습니까? 아니면 코드로 JSON –

+0

을 보냈습니까? 사용자 정의 모델 바인더가 사용되지 않습니다. – Martijn

답변

0

마지막으로 msn 블로그에서 awnser를 발견했습니다. 클라이언트가 .NET 응용 프로그램이 아니기 때문에

https://blogs.msdn.microsoft.com/waws/2017/04/03/posting-a-large-file-can-fail-if-you-enable-client-certificates/

우리의 솔루션은 첫 번째 옵션이다. 치트 같아 보이지만 작동합니다.

(나는 보존에 대한 링크에서 텍스트를 복사, 아래에 그것을 찾기 위해 정말 어렵 기 때문에) :

개요

클라이언트 인증서 및 POST가 필요하거나 많은 양을 넣으면 데이터가 없으면 요청이 실패 할 수 있습니다. 이것은 적어도 10 년 동안 IIS와 함께 존재해온 문제였습니다 (IIS를 사용하기 때문에 Windows 플랫폼의 Azure App Services에도 적용됩니다). 이것에 대한 정보가 많지 않으므로이 블로그는이 문제를 명확히하는 데 도움이 될 것입니다. 이 솔루션은 매우 간단합니다!

문제는

HTTPS (TCP)에 대한 기본 프로토콜 하나 개 이상의 프레임에 대량의 데이터 패킷을 나눌 것입니다. 일반적으로 이것은 응용 프로그램에서는 문제가 아니며 클라이언트와 서버 모두에 투명합니다. 클라이언트 인증서를 필요로하는 일부 응용 프로그램은 초기 데이터가 여러 프레임으로 푸시되고 IIS 서버에서 클라이언트 인증서를 요구하기 전에 문제가 발생할 수 있습니다. 데이터가 클라이언트에서 서버로 흐르기 시작하면 (서버 Hello의 초기 SSL 핸드 셰이크 후) 데이터의 첫 번째 패킷이 전송되면 실제로 네트워크 추적에서이를 볼 수 있습니다. 서버 응답은 클라이언트 인증서에 대한 요청의 시작이며 클라이언트에서 오는 다음 패킷에 더 많은 데이터가 포함됩니다. 이 시점에서 서버는 클라이언트 인증서가 될 것으로 예상되는 데이터의 다음 데이터를 예상하므로 오류가 발생합니다. 전체 게시물에 대한 요청 또는 PUT이 완료하기 때문에 데이터의 작은 패킷으로 발생하지 않습니다 서버가 얻는 다음 것은 클라이언트 인증서 핸드 쉐이크와 PUSH에서되지 않은 추가 데이터입니다 또는 PUT

해상도

이 문제를 해결하기 위해, 당신은 단순히이 두 가지 기술 중 하나 활용해야합니다 설정 HEAD 요청

  • 와 먼저 연결을 설정

    • 을 기대 : 100 - 계속 요청 헤더를

    옵션 1 : 먼저 HEAD 요청으로 연결 설정 다음 옵션만큼이나 마음에 들지 않지만 성공적으로 작동합니다.개념은 HEAD 요청에 전혀 데이터가없고 문제없이 SSL 연결을 설정한다는 것입니다. 그런 다음 HTTP 라이브러리의 기본 구현을 사용하여이 연결을 재사용하면 (대부분 수행) 더 이상 SSL 핸드 셰이크가 발생하지 않으며 문제를 피할 수 있습니다.

    옵션 2 : 다음과 같이 Expect : 100-continue 헤더를 다음과 같이 설정하십시오. 요청은 이 최선의 방법입니다. RFC에 따르면 이것이 실제로 존재하는 이유입니다! 간단히 말해서 서버가 요청 (SSL 협상 후)을 준비하면 100 개의 상태가 복원되고 데이터를 POST 또는 PUT 할 수 있습니다. 모든 HTTP 클라이언트 라이브러리는 RFC의 일부이므로이 기능을 구현하므로 간단하며 작동하도록 보장됩니다. 다음은 HttpWebRequest (또는 그 파생물)를 사용할 때 .NET에서 설정하는 샘플입니다. 코드에서 HTTP 요청을하기 전에 코드에서 한 번 수행합니다 (예 : global.asax 또는 Startup.cs의 경우) ServicePointManager.Expect100Continue = true 참조 : ServicePointManager.Expect100Continue 속성 새로운 HttpClient 클래스를 사용하는 경우이 코드가 자동으로 추가됩니다 이 십년 이상 동안 문제되어 있지만 (분명한 이유).

    요약 텍스트을 강조,이 헤더를 기대하기 때문에 대부분 공공 직면 문서 (그것의 방법을 못 찾았을위한 가장 좋은 방법입니다 우리들의 구식 타입들과 최신 클래스들과 라이브러리들은 모두 디폴트로이 헤더를 포함합니다.)

  • 0

    귀하의 요청에 따라 IIS 제한에 도달 할 수 있습니다. 로서 설명 requestLimits 대한 Length 요청 헤더 속성으로서 다음과

    는 바이트 요청 콘텐츠의 최대 길이를 지정한다.

    기본값은 30000000.

    나는 다음과 같이 당신이 Length 요청 헤더을 증가시킬 수 있다고 가정 :

    <security> 
        <requestFiltering> 
        <!-- Measured in Bytes --> 
        <requestLimits maxAllowedContentLength="1073741824" /> <!-- 1 GB, Byte in size, up to 2GB--> 
        </requestFiltering> 
    </security> 
    
    나는 당신이 당신의 요청 본문 크기를 확인하려고 추천 할 것입니다

    이 문제를 줄이려면 maxAllowedContentLength를 늘리십시오. 또한 issue에서 ASP.NET Core 2.0.0의 요청 크기 제한에 대해 이야기했습니다. 또한 비슷한 문제가 있습니다. here을 참조하십시오.

    +0

    JSON 요청이 그리 크지 않습니다. 134,977 자 (+/- 136.95KB)의 JSON 요청이 실패합니다. 나는 2 분 후에 우편 배달부로부터 시간 제한 만 받는다. 개발 환경에서 응답은 0.5 초 내에 있습니다. 나는 당신의 제안을 적용했지만 행동에 변화는 없었습니다. – Martijn