NodeJS-“소켓 끊기”는 실제로 무엇을 의미합니까?
Node 및 Cheerio를 사용하여 웹 스크레이퍼를 구축 중이며 특정 웹 사이트의 경우 다음 오류가 발생합니다 (이 웹 사이트에서만 발생합니다.
매번 다른 위치에서 발생하므로 때로는 url x오류가 발생하고 다른 시간 url x은 괜찮으며 완전히 다른 URL입니다.
Error!: Error: socket hang up using [insert random URL, it's different every time]
Error: socket hang up
at createHangUpError (http.js:1445:15)
at Socket.socketOnEnd [as onend] (http.js:1541:23)
at Socket.g (events.js:175:14)
at Socket.EventEmitter.emit (events.js:117:20)
at _stream_readable.js:910:16
at process._tickCallback (node.js:415:13)
이것은 디버깅하기가 매우 까다 롭습니다. 처음부터 시작 해야할지 모르겠습니다. 시작하려면, 무엇 인가 소켓 오류를 끊지? 404 오류입니까 아니면 비슷한가요? 아니면 서버가 연결을 거부했음을 의미합니까?
나는 이것에 대한 설명을 찾을 수 없다!
편집 : 다음은 (때로는) 오류를 반환하는 코드 샘플입니다.
function scrapeNexts(url, oncomplete) {
request(url, function(err, resp, body) {
if (err) {
console.log("Uh-oh, ScrapeNexts Error!: " + err + " using " + url);
errors.nexts.push(url);
}
$ = cheerio.load(body);
// do stuff with the '$' cheerio content here
});
}
연결을 닫으라는 직접 전화는 없지만, Node Request내가 말할 수있는 한 사용하고 http.get있으므로 이것이 필요하지 않습니다. 잘못되면 정정하십시오!
편집 2 : 여기에 오류를 일으키는 실제 사용중인 코드가 있습니다. prodURL다른 변수는 대부분 이전에 정의 된 jquery 선택기입니다. asyncNode 용 라이브러리를 사용합니다 .
function scrapeNexts(url, oncomplete) {
request(url, function (err, resp, body) {
if (err) {
console.log("Uh-oh, ScrapeNexts Error!: " + err + " using " + url);
errors.nexts.push(url);
}
async.series([
function (callback) {
$ = cheerio.load(body);
callback();
},
function (callback) {
$(prodURL).each(function () {
var theHref = $(this).attr('href');
urls.push(baseURL + theHref);
});
var next = $(next_select).first().attr('href');
oncomplete(next);
}
]);
});
}
socket hang up던져 질 때 두 가지 경우 가 있습니다 :
당신이 클라이언트 인 경우
클라이언트가 원격 서버에 요청을 보내고 적시에 응답을받지 못하는 경우. 소켓이 종료 되어이 오류가 발생합니다. 이 오류를 잡아서 처리 방법을 결정해야합니다 (요청을 재 시도할지, 나중에 대기할지 등).
서버 / 프록시 인 경우
서버, 아마도 프록시 서버 인 경우 클라이언트로부터 요청을 수신 한 후 해당 서버에 대한 조치를 시작하거나 (업스트림 서버로 요청을 중계) 응답을 준비하기 전에 클라이언트는 취소 / 중단하기로 결정합니다. 요청.
이 스택 추적은 클라이언트가 요청을 취소 할 때 발생하는 상황을 보여줍니다.
Trace: { [Error: socket hang up] code: 'ECONNRESET' }
at ClientRequest.proxyError (your_server_code_error_handler.js:137:15)
at ClientRequest.emit (events.js:117:20)
at Socket.socketCloseListener (http.js:1526:9)
at Socket.emit (events.js:95:17)
at TCP.close (net.js:465:12)
라인 은 @Blender가 위에서 언급 한 http.js:1526:9것과 동일하게 지적합니다 socketCloseListener.
// This socket error fired before we started to
// receive a response. The error needs to
// fire on the request.
req.emit('error', createHangUpError());
...
function createHangUpError() {
var error = new Error('socket hang up');
error.code = 'ECONNRESET';
return error;
}
클라이언트가 브라우저의 사용자 인 경우가 일반적입니다. 일부 리소스 / 페이지를로드하는 데 시간이 오래 걸리고 사용자는 단순히 페이지를 새로 고칩니다. 이러한 조치로 인해 서버 측에서이 오류가 발생하는 이전 요청이 중단됩니다.
이 오류는 클라이언트의 희망으로 인해 발생하므로 오류 메시지가 나타나지 않습니다. 따라서이 오류를 중요하다고 생각할 필요는 없습니다. 그냥 무시해 이러한 오류로 인해 res클라이언트 가 수신 한 소켓이 여전히 쓰기 가능하지만 손상 되었기 때문에 권장됩니다 .
console.log(res.socket.destroyed); //true
따라서 응답 객체를 명시 적으로 닫는 것을 제외하고는 아무것도 보내지 않아도됩니다.
res.end();
그러나, 당신이 무엇을 해야 당신이 경우에 확실 하다 이미 상류에 요청을 전달했다 프록시 서버, 다시 상류을 말할 것이다 응답에서 관심의 부족을 나타내는 상류에 내부 요청을 중단하는 것입니다 아마도 고가의 작업을 중지하기 위해 서버.
소스를 살펴보십시오 .
function socketCloseListener() {
var socket = this;
var parser = socket.parser;
var req = socket._httpMessage;
debug('HTTP socket close');
req.emit('close');
if (req.res && req.res.readable) {
// Socket closed before we emitted 'end' below.
req.res.emit('aborted');
var res = req.res;
res.on('end', function() {
res.emit('close');
});
res.push(null);
} else if (!req.res && !req._hadError) {
// This socket error fired before we started to
// receive a response. The error needs to
// fire on the request.
req.emit('error', createHangUpError());
req._hadError = true;
}
}
서버가 응답을 보내지 않으면 메시지가 생성됩니다.
언급 할 가치가있는 한 가지 사례 : Express를 사용하여 Node.js에서 Node.js로 연결할 때 요청 된 URL 경로 앞에 "/"를 붙이지 않으면 "소켓 끊기"가 발생합니다.
내가 사용하는 require('http')소비 HTTPS 서비스를하며 "보여 주었다 socked hang up".
그런 다음 require('https')대신 사용 하고 작동합니다.
아래는 아래 예제에서 주석이 달린 코드를 추가하지 못했을 때 동일한 오류가 발생하는 간단한 예입니다. 코드 req.end()를 주석 해제하면 이 문제가 해결됩니다.
var fs = require("fs");
var https = require("https");
var options = {
host: "en.wikipedia.org",
path: "/wiki/George_Washington",
port: 443,
method: "GET"
};
var req = https.request(options, function (res) {
console.log(res.statusCode);
});
// req.end();
블렌더의 대답을 확장하면 여러 상황에서 발생합니다. 내가 만나는 가장 일반적인 것은 다음과 같습니다.
- 서버가 충돌했습니다.
- 서버가 귀하의 연결을 거부했습니다
User-Agent.
socketCloseListener블렌더의 답변에 요약 된 것처럼 끊기 오류가 생성되는 유일한 장소는 아닙니다.
예를 들어, 여기에 있습니다 :
function socketOnEnd() {
var socket = this;
var req = this._httpMessage;
var parser = this.parser;
if (!req.res) {
// If we don't have a response then we know that the socket
// ended prematurely and we need to emit an error on the request.
req.emit('error', createHangUpError());
req._hadError = true;
}
if (parser) {
parser.finish();
freeParser(parser, req);
}
socket.destroy();
}
당신은 시도 할 수 curl헤더와 함께 노드에서 발송하고 당신이 응답을 얻을 수 있는지 확인하고되도록. 로 응답이 curl없지만 브라우저에서 응답을 받으면 User-Agent헤더가 차단되었을 가능성이 큽니다.
언급 할 가치가있는 또 다른 경우 (Linux 및 OS X의 경우)는 https요청 수행 과 같은 라이브러리를 사용 하거나 https://...로컬로 제공되는 인스턴스의 URL로 전달 443하면 예약 된 개인 포트 인 포트를 사용하고 끝나 Socket hang up거나 ECONNREFUSED오류가 발생 했을 수 있습니다 .
대신 port 3000, fe를 사용 하고 http요청하십시오.
Nano 라이브러리를 사용하여 Couch DB 에 연결하는 동안 동일한 문제가 발생했습니다 . keepaliveagent 라이브러리 를 사용하여 연결 풀링을 미세 조정하려고 시도했지만 소켓 끊기 메시지로 계속 실패했습니다 .
var KeepAliveAgent = require('agentkeepalive');
var myagent = new KeepAliveAgent({
maxSockets: 10,
maxKeepAliveRequests: 0,
maxKeepAliveTime: 240000
});
nano = new Nano({
url : uri,
requestDefaults : {
agent : myagent
}
});
약간의 어려움을 겪은 후에 나는 문제를 해결할 수있었습니다. HTTPS 프로토콜을 통해 데이터베이스에 연결하고 있었지만이 라이브러리 쇼의 사용 예제로 생성 된 keepalive 에이전트 (http를 사용하는 일부 기본값에 의존 함)를 nano 객체에 계속 전달했습니다.
HttpsAgent 를 사용하기 위한 간단한 변경으로 트릭을 수행했습니다.
var KeepAliveAgent = require('agentkeepalive').HttpsAgent;
여기에 나열된 모든 작업을 수행하면서 문제가 발생했지만 여전히 오류가 발생했습니다. req.abort ()를 호출하면 실제로 ECONNRESET 코드와 함께 오류가 발생하므로 실제로 오류 처리기에서 오류를 잡아야합니다.
req.on('error', function(err) {
if (err.code === "ECONNRESET") {
console.log("Timeout occurs");
return;
}
//handle normal errors
});
일부 서버에 요청하는 동안 동일한 문제가 발생했습니다. 필자의 경우 요청 옵션의 헤더에서 값을 User-Agent로 설정하면 도움이되었습니다.
const httpRequestOptions = {
hostname: 'site.address.com',
headers: {
'User-Agent': 'Chrome/59.0.3071.115'
}
};
일반적인 경우는 아니며 서버 설정에 따라 다릅니다.
대한 request모듈 사용자
타임 아웃
시간 종료에는 연결 시간 종료 및 읽기 시간 종료 의 두 가지 주요 유형이 있습니다. 연결 시간 초과는 클라이언트가 원격 컴퓨터 (에 대응에 대한 연결 설정을 시도하는 동안 타임 아웃이 충돌하는 경우 발생
connect()소켓에 호출). 읽기 제한 시간은 서버가 응답의 일부를 다시 보낼 너무 느립니다 언제든지 발생합니다.
하는 것으로 연결 시간 제한은 방출 ETIMEDOUT오류 및 읽기 시간 초과 방출 ECONNRESET오류가 발생했습니다.
또한 이유는 사용이 될 수 app인스턴스 express대신 server에서 const server = http.createServer(app)서버 소켓을 만드는 동안을.
잘못된
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
app.use(function (req, res) {
res.send({ msg: "hello" });
});
const wss = new WebSocket.Server({ server: app }); // will throw error while connecting from client socket
app.listen(8080, function listening() {
console.log('Listening on %d', server.address().port);
});
옳은
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
app.use(function (req, res) {
res.send({ msg: "hello" });
});
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
server.listen(8080, function listening() {
console.log('Listening on %d', server.address().port);
});
나는 웹 (노드)과 안드로이드 개발을 모두하고 안드로이드 스튜디오 장치 시뮬레이터와 도커를 함께 열고 포트 8601을 사용합니다. socket hang up안드로이드 스튜디오 장치 시뮬레이터를 닫은 후 오류가 발생했으며 노드 측에서 잘 작동합니다. Android Studio 기기 시뮬레이터와 도커를 함께 사용하지 마십시오.
필자의 경우 응용 프로그램 / json 응답의 형식이 잘못 되었기 때문입니다 (스택 추적 포함). 응답이 서버로 전송되지 않았습니다. 로그가 없기 때문에 디버깅하기가 매우 까다 롭습니다. 이 스레드는 어떤 일이 발생했는지 이해하는 데 도움이됩니다.
node-http-proxy를 사용하는 경우이 문제에 유의하여 소켓 끊기 오류가 발생합니다 ( https://github.com/nodejitsu/node-http-proxy/issues/180) .
이 링크에서 해결을 위해 express.bodyParser () 전에 Express 경로 내에서 API 경로 선언 (프록시 용)을 이동하십시오.
어제 IntelliJ IDEA 2016.3.6을 통해 웹 응용 프로그램 및 node.js 서버를 실행 하여이 문제에 부딪 쳤습니다. Chrome 브라우저에서 쿠키를 삭제하고 캐시하기 만하면됩니다.
https 연결을 통해이 오류가 발생하고 즉시 발생하는 경우 SSL 연결을 설정하는 데 문제가있을 수 있습니다.
나 에게이 문제는 https://github.com/nodejs/node/issues/9845 였지만 당신에게는 다른 것일 수 있습니다. SSL에 문제가 있으면 도메인에 연결하려고 시도하는 nodejs tls / ssl 패키지를 사용하여이를 재생할 수 있어야합니다.
주목할만한 가치가 있다고 생각합니다 ...
Google API에 대한 테스트를 작성했습니다. 임시 서버로 요청을 가로 채고 실제 API로 전달했습니다. 요청에서 헤더를 전달하려고했지만 일부 헤더가 다른 쪽 표현에 문제를 일으켰습니다.
즉, 내가 삭제했다 connection, accept그리고 content-length헤더를 따라 전달하도록 요청 모듈을 사용하기 전에.
let headers = Object.assign({}, req.headers);
delete headers['connection']
delete headers['accept']
delete headers['content-length']
res.end() // We don't need the incoming connection anymore
request({
method: 'post',
body: req.body,
headers: headers,
json: true,
url: `http://myapi/${req.url}`
}, (err, _res, body)=>{
if(err) return done(err);
// Test my api response here as if Google sent it.
})
내 경우에는 오류가 아니지만 크롬 브라우저의 예상 동작입니다. Chrome은 tls 연결을 활성 상태로 유지하지만 (속도는 제 생각에는 2 초) node.js 서버는 2 분 후에 중지하고 오류가 발생합니다.
에지 브라우저를 사용하여 GET 요청을 시도하면 전혀 오류가 없습니다. 크롬 창을 닫으면 즉시 오류가 발생합니다.
그래서 뭐 할까? 1)이 오류는 실제로 오류가 아니기 때문에 필터링 할 수 있습니다. 2) 아마도 더 나은 해결책이 있습니다 :)
참고 URL : https://stackoverflow.com/questions/16995184/nodejs-what-does-socket-hang-up-actually-mean
'development' 카테고리의 다른 글
| 프로그래밍 방식으로 RelativeLayout에서 뷰를 레이아웃하는 방법은 무엇입니까? (0) | 2020.04.15 |
|---|---|
| 내용 처리 : "인라인"과 "첨부 파일"의 차이점은 무엇입니까? (0) | 2020.04.15 |
| 다중 파일 Go 프로젝트 구성 (0) | 2020.04.15 |
| 더하기 기호는 '+ new Date'에서 무엇을합니까 (0) | 2020.04.15 |
| application / x-javascript와 text / javascript 컨텐츠 유형의 차이점 (0) | 2020.04.15 |