我想从我的Node服务器向Twitter发出GET
请求,解析响应数据,并通过websocket
(ws,而不是wss)连接发送。一切正常 - 除了30秒后(我计时,它总是30 +/- 1秒),套接字连接挂起,我得到以下错误堆栈:
Error: socket hang up
at createHangUpError (_http_client.js:200:15)
at TLSSocket.socketOnEnd (_http_client.js:292:23)
at emitNone (events.js:72:20)
at TLSSocket.emit (events.js:166:7)
at endReadableNT (_stream_readable.js:905:12)
at nextTickCallbackWith2Args (node.js:442:9)
at process._tickCallback (node.js:356:17)
我一直在使用与Twitter的公共流相同的服务器设计,它运作良好。只有在实现GET
请求时才会发生挂断。
到目前为止,我已经尝试了以下解决方案:
keepAliveAgent
设置为我的GET请求选项npm
模块)代理KeepAliveInterval
,keepaliveGracePeriod
,
和套接字服务器上的dropConnectionOnKeepaliveTimeout
一切都无济于事。该应用程序保持精美的工作30秒;然后,它就会挂掉。
我的下一个主角:Twitter要求通过HTTPS发送仅应用程序身份验证的请求。我没有在我的代码中为不同的安全级别做出任何规定。我现在要对此进行跟进 - 看看SO社区是否有任何想法。非常感谢您提供的任何帮助!
以下是代码,简要介绍:
// Initialize basic server for the web socket requests
var handShakeServer = http.createServer(function(request, response) {
console.log((new Date()) + ' Received request for ' + request.url);
response.writeHead(404);
response.end();
});
handShakeServer.listen(8080, function() {
console.log((new Date()) + ' Socket server is listening on port 8080');
});
// Initialize the socket server itself.
var socketServer = new WebSocketServer({
httpServer: handShakeServer,
autoAcceptConnections: false,
keepAliveInterval: (3600 * 1000),
dropConnectionOnKeepaliveTimeout: false
});
// On request, listen for messages.
socketServer.on('request', function(request) {
// Initialize connection from verified origin
var connection = request.accept('echo-protocol', request.origin);
// On message (search params from client), query Twitter.
connection.on('message', function(message) {
// BEARER_ACCESS_TOKEN is for Twitter's application-only authentication
var options = {
'path': '/1.1/search/tweets.json?q=stuff',
'hostname': 'api.twitter.com',
'method': 'GET',
'headers': {
'Authorization': ('Bearer ' + process.env.BEARER_ACCESS_TOKEN),
'Accept': '*/*'
},
'agent': agent,
'port': 443,
};
// Query twitter via HTTPS GET, listen for response
var req = new https.request(options, function(res) {
var responseString = '';
// On data, concatenate the chunks into a whole JSON object
res.on('data', function(tweet) {
responseString += tweet;
});
// On completion of request, send data to be analyzed.
res.on('end', function() {
// Once returned, send data to client through socket connection.
var result = doSomeAnalysis(JSON.parse(responseString));
connection.sendUTF(JSON.stringify(result));
});
});
// The https request is done; terminate it.
req.end();
});
});
此外,在Web套接字客户端,我有:
client.connect('ws://localhost:8080/', 'echo-protocol', 'twitterQuery');
以下是我的server.js中的相关模块:
var util = require('util');
var https = require('https');
var http = require('http');
var WebSocketServer = require('websocket').server;
var HttpsAgent = require('agentkeepalive').HttpsAgent;
答案 0 :(得分:0)
确定!原来的HTTPS兼容性不会导致挂断。当我完全将websocket连接逻辑与Twitter请求逻辑分离并将console.log虚函数放在他们曾经重叠的地方时,Twitter查询工作正常,但是websocket连接让我挂起了挂断错误,就像以前一样 - 总是在30之后秒,并且始终无论通过连接发送了多少数据。
修复:手动设置ping / pong度量,以两种方式之一(或两种方式,以获得额外冗余)方式:
//SERVER SIDE:
// Option 1: Use the npm module's event 'ping'
connection.on('ping', function(data){
console.log('Server: ping received at: ' + (new Date()))
})
// Option 2: Use the more generalized event 'message', look for your
// custom 'ping' message
connection.on('message', function(message){
console.log("Socket server received message from client.")
if (message.utf8Data == 'ping'){
console.log('pong!')
}
})
//CLIENT SIDE:
setInterval(function(){
if (connection.connected){
// To match Option 1 above, use this:
connection.ping();
// To match Option 2 above, use this:
connection.sendUTF('ping');
}
}, 19900)
connection.on('pong', function(){
console.log('Client: pong received at: ' + (new Date()) + '\n')
})
所以,最后,一个非常基本的修复。我不明白为什么连接需要这些保持活着的ping,因为Twitter响应在它退出我的分析功能后立即通过连接以~1秒的间隔通过管道传输,保持连接非常活跃(但不会过载) )。请参阅我的原始帖子,了解这种情况:
// Once returned, send data to client through socket connection.
var result = doSomeAnalysis(JSON.parse(responseString));
connection.sendUTF(JSON.stringify(result));
可能是因为没有'pong'被发送回服务器,因此,即使websocket连接保持其数据飞出,它也不知道它的接收端是否仍然是活动的。但是 - 为什么我的流媒体活动不需要相同的衡量标准?它通过相同的频道工作,一旦流媒体开始就不会从客户端收到任何数据(没有'pong'),并且将永久地继续(直到Google地理编码关闭我,即:)。
我想,通过推断,默认情况下必须在流中存在一些保持活动的ponging,并且我需要手动将其添加到GET请求中,因为我本质上是将批处理响应绑定到流出,小块的小块,因为返回退出我的分析函数。
冷却。无论如何,我以为我会留下这个(太冗长)的帖子,以防任何人因使用大数据块的GET请求而被挂起(双关语!),然后通过您的网络套接字连接进行虚假流媒体传输。组合确实很好用,解决了这个问题。