2013-10-29 3 views
0

Node.js의 이벤트 루프 특성으로 인해 요청이 이미 콜백으로 전달 된 후 쉽게 처리되지 않도록 할 수 없습니다 기능.요청 시간 초과시 처리 중지 요청

각 이벤트 콜백은 다른 특정 프로세스 흐름이나 이벤트에 연결되지 않기 때문에 콜백이 이벤트 루프 대기열에 추가되거나 현재 처리중인 경우 request.on (' timeout ') 핸들러가 트리거됩니다.

요청이 시간 초과되면 처리를 중단 할 수있는 방법이 있습니까? 이 문제를 부분적으로 해결하기 위해 생각할 수있는 유일한 방법은 요청 중에 요청이 실행되었는지 확인하기 위해 실행되는 각 비동기 콜백의 맨 위에 체크를 추가하는 것입니다. 요청이 만료 된 경우 즉시 반환하고 중지합니다. 연속 콜백.

그러나 제한 시간 초과 요청으로 처리 된 미해결 비동기 호출이 이미있는 경우이 방법으로 문제가 해결되지 않습니다. 이 경우 비동기 처리 (예 : MySQL 쿼리 실행)를 수행중인 모든 연결을 끊지 않는 한 연결이 계속 진행되고 결국 비동기 콜백이 호출됩니다.

apache는 들어오는 요청마다 새로운 PHP 프로세스를 생성하므로 PHP + Apache와 같은 다른 프로그래밍 패러다임에서는 문제가되지 않으므로 요청 시간 초과로 결국 프로세스가 종료되고 전체 실행 흐름이 중지됩니다.

누구든지이 문제를 겪고 있으며 쉽게이 문제를 해결할 수있는 기존의 라이브러리 또는 맞춤 방식을 발견 했습니까?

편집 : 지금 우리가 다음 응답을 반환, 토끼 큐에 요청 데이터를 게시, 분석을 추적하기 위해 들어오는 요청을 처리하는 노드에 구축 된 API를

: 구체적인 예를 추가합니다. 요청이 들어오고 어떤 이유로 처리가 30 초보다 오래 걸리면 시간이 초과되고 오류 응답이 클라이언트로 전송됩니다. 이 시점에서 클라이언트는 동일한 호출을 다시 시도합니다 (분석을 잃지 않음).

그러나 요청 자체와 토끼 발행 요청 간에는 아무런 관련이 없으므로 (게시를 시작한 요청을 제외하고) 해당 데이터의 게시를 중단 할 수있는 방법이 없습니다. 따라서 토끼 서버가 결국 게시 요청 처리를 끝내면 클라이언트가 이제 2 (또는 그 이상) 요청을했기 때문에 중복 데이터가있게됩니다.

처음 요청을 게시를 중단하는 유일한 방법은 요청 시간이 초과되면 토끼 연결을 끊는 것입니다. 이렇게하면 초기 게시가 중단되고 클라이언트의 재시도 요청이 복제를 요청하지 않습니다. 그러나 동일한 유형의 수동 연결 파괴는 요청 전체에서 이루어진 비동기 호출에 대해 수행해야합니다. 타임 아웃이 발생했을 때 5 개의 비동기 호출이 있으면 5 개의 비동기 연결 (토끼, mysql, 몽고 등과의 연결 여부)을 모두 파괴해야합니다.

그러나 문제는 요청 시간이 초과되었을 때 이미 설정된 연결을 넘어선 다. 토끼에 게시하기 전에 요청 시간이 시작된 경우에도 해당 요청을 처리하기 위해 호출 된 함수가 이미 실행되었으며 요청이 시간 초과되어 반환되는지 여러 위치에서 확인하지 않으면 중지되지 않습니다 바로.

+0

id (클라이언트 IP 또는 쿠키 값 등)를 사용하여 전역 객체에 토끼 연결을 저장할 수 있으며 다음 요청시이 연결을 검색 할 수 있습니다. 또한 토끼 연결을 소켓 자체에 저장하고 '닫기'를 듣고 토끼 연결을 끊을 수 있습니다. Killing은 'close'를 호출하거나 플래그를 설정하여 자신의 코드에서 bails하는 것을 의미합니다. 첫 번째 옵션으로 가면, 여러 개의 소켓/HTTP 연결을 단일 서버 '연결'에 수렴시킬 수 있습니다. – DDS

+0

@DDS 지금은 토끼 연결을 요청에 첨부 한 다음 제한 시간이 지나면 연결을 끊습니다. 그러나 전체 요청 흐름을 처리하지 못하도록하는보다 포괄적 인 솔루션을 원합니다. 노드에 완전히 반하는 (각 들어오는 요청에 대해 새로운 프로세스를 생성하는) 노드를 소개하거나 중복/자세한 정보를 표시하지 않는 한 지금은 좋은 방법을 생각할 수 없습니다 (각 비동기 호출 전에 확인을 추가하여 요청 시간이 초과되었습니다). 이 방법들 중 하나는 매우 직관적이지 않습니다. – Sarah

+0

노드 0.11.x를 사용하는 경우 생성기 기반 함수 ([gen-run] (https : // github.co.kr/creationix/gen-run), [suspend] (https://github.com/jmar777/suspend)), 함수를 중단하려는 경우 생성기 함수에 예외를 던지도록 수정할 수 있습니다. 원래의 다음 콜백은 무시됩니다. 그런 다음 '실행중인 기능'(실제로는 일시 중지됨)에서 실제 '중단'통화를 할 수 있습니다. 이것은 본질적으로 각 콜백 호출 후에 점검을하고 함수 이탈로 끝까지 밀어 넣습니다 (오류를 포착하고 무시하지 않는 한). – DDS

답변

1

좀 더 구체적인 질문을하면 더 나은 답변을 얻을 수 있습니다. "mysql 쿼리"와 같은 기술적 세부 사항은 "요청"과 같이 모호하지 않은 비 기술적 인 용어보다 쉽게 ​​논의 할 수 있습니다.

나는 부분적으로이 문제를 해결하기 위해 생각할 수있는 유일한 방법이있는 경우 요청이 시간 초과되지 않았는지 요청시 실행될 때마다 비동기 콜백의 상단에 수표를 추가하는 것입니다, 그럼 즉시 반환하고 연속 콜백을 중지하십시오.

node.js.에서 코드를 작성하지 않아도됩니다. 아무 문제가 없기 때문에 아무도 그렇게하지 않습니다. 그랬다 할지라도 응용 프로그램보다 스택에서 더 낮은 값을 해결하는 것이 좋습니다. 아파치는 들어오는 각 요청에 대한 새로운 PHP 프로세스를 생성하므로 공정 밖으로 요청 시간이 결국 사망하고 경우 전체 실행 흐름이 정지되기 때문에

이것은 PHP + 아파치와 같은 다른 프로그래밍 패러다임에 문제가되지 않습니다.

들어오는 HTTP 요청의 경우 새 프로세스 또는 새 스레드조차 없기 때문에 이것은 node.js의 문제보다 적습니다. 무슨 일이 끝 것은 본질적으로 :

  • 클라이언트가 연결하고 OS는
  • 노드가
  • 이의이 시점 클라이언트 프로세스 (브라우저)에서 가정 해 봅시다 GET 요청을 수신 연결을 수신
  • GET 요청을 보낸다 갑자기 클라이언트 컴퓨터에서 죽었습니다.
  • 정확히 어떻게 작동하는지는 몇 가지 시나리오가 있습니다. 브라우저가있는 집에서 전원이 꺼지면 유선이 나오지 않고 다른 시나리오에서는 클라이언트가 TCP 연결을 일찍 종료하기 위해 패킷을 보냅니다.
  • 그러나 노드 측에서 실제로는은 중요하지 않습니다. 요청을 처리하고 DB 쿼리를 작성하고 HTML을 렌더링하며 최악의 경우는 일단 작업이 완료되면 아무도 신경 쓰지 않지만 단지 하나의 GET 요청 일뿐입니다. 응용 프로그램은 초당 이러한 많은 작업을 수행해야합니다. 그 요청을 "문제"로 처리하는 것을 생각하는 것은 잘못된 것입니다. 그것은 문제가 아니며, 프로그래밍 언어로 현실적으로 할 수있는 것에 대해 들어 본 적이 없습니다. 서버는 글자 그대로 200ms 전 전력을 잃어버린 클라이언트의 응답을 정확하게 기다리는 클라이언트를 구분할 수 없습니다. HTTP에는 "CANCEL"메소드가 없습니다. 사실 전체 HTTP 요청을 완료하는 것이 더 의미 상 정확합니다. 예를 들어, 웹 브라우저가 신용 카드 구매에 대한 완전한 HTTP POST를 보내지 만 응답하기 전에 연결을 끊으면 해당 트랜잭션이 완료 될 것입니다. 시작한 후 중단하려면 올바르지 않습니다.
+0

동의하지 않습니다. 모든 http 요청이 잠시 동안 제공되지 않습니다. 일부는 몇 시간 (다운로드)이 걸릴 수도 있고 상당한 리소스가 필요할 수도 있습니다 (큰 파일 읽기). 또한, 이들은 클라이언트에 의해 떨어질 가능성이 매우 큽니다 (기다리는 것이 지겨워). 이를 고려하여 조기 퇴직을하는 것이 유리할 수 있습니다. AFAICT, Sarah는 당신이 수동으로해야한다고 말하면 옳습니다. 즉, 모든 콜백마다이 작업이 필요하지는 않습니다. 루프가있는 경우 루프를 해제하는 것으로 충분합니다. 루프 나 파이프가 없으면 초기 응답 메커니즘 (응답 상태)을 제공하는 것이 그다지 가치가 없을 것입니다. – DDS

+0

아, 예, 분명합니다. 구체적인 예를 통해 확실한 답을 얻을 수 있습니다. 다운로드는 불특정 노드/PHP 응용 프로그램에 대한 낮은 비율입니다. FUD를 기반으로 한 일반적인 질문은 광범위한 대답을 얻습니다. –

+0

광범위하고 광범위한 문제이므로 광범위한 답변을 찾고 있습니다. 명시 적 또는 암시 적 시간 종료 또는 요청 취소가 발생할 때마다 문제가 발생합니다. 어떤 이유로 든 요청이 닫히는 경우 (시간 초과 또는 요청이 클라이언트에 의해 닫히거나 행 아래에 있기 때문에) 요청의 처리를 쉽게 중지 할 수 없습니다. 좀 더 명확히하기 위해 편집을 참조하십시오. – Sarah