2016-03-30 2 views
0

Я хочу сделать запрос GET с моего сервера Node на Twitter, проанализировать данные ответа и отправить его через соединение (ws, not wss). Все работает - за исключением того, что через 30 секунд (я засек, это всегда 30 +/- 1 сек), подключение к сокету вешает трубку, и я получаю следующее сообщение об ошибке: стекSocket повесить трубку: Websocket GET HTTPS запрос на Twitter API

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 происходит зависание.

До сих пор, я попытался следующие решения:

  • дроссельного запрос входящей скорости Waaaay вниз с низким значением счета в Ури закодированных строк запроса Twitter; Тайм-аут происходит даже с 1 твит отправлены обратно ко мне, еще через ~ 30 секунд
  • установить keepAliveAgent мои параметры запроса GET
  • попытался вручную встроенный (не npm модуль) агента для запроса
  • набор KeepAliveInterval, keepaliveGracePeriod , и dropConnectionOnKeepaliveTimeout на сокет сервера
  • и кучу УЗЕЛ newbish вещей

все без толку. Приложение прекрасно работает в течение 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(); 
 
    }); 
 
});

Кроме того, на стороне клиента веб-сокет, у меня есть:

client.connect('ws://localhost:8080/', 'echo-protocol', 'twitterQuery'); 

И здесь являются модули, имеющие отношение к моему серверу.js:

var util    = require('util'); 
var https   = require('https'); 
var http    = require('http'); 
var WebSocketServer = require('websocket').server; 
var HttpsAgent  = require('agentkeepalive').HttpsAgent; 

ответ

0

Хорошо! Оказывается, совместимость с HTTPS не вызывает зависания. Когда я полностью развязал логику соединения с веб-узлом из логики запроса Twitter и поставил объекты-заглушки console.log, где они накладывались друг на друга, запрос Twitter работал нормально, но соединение с веб-узлом бросило мне ошибку зависания точно так же, как и раньше - всегда после 30 секунд и всегда независимо от того, сколько данных было отправлено по соединению.

Исправление: Вручную установить в пинг-понг/мер, в одном из двух (или оба, для дополнительной избыточности) способы:

//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') 
    }) 

Таким образом, в конце концов, очень простой фикс.Я не понимаю, почему соединение требует, чтобы эти сообщения были сохранены, поскольку ответ Twitter отправляется напрямую через соединение сразу после выхода из моей функции анализа через ~ 1 секунду, поддерживая соединение чрезвычайно активно (но не перегружая). Смотрите мой оригинальный пост для того, где это происходит:

// Once returned, send data to client through socket connection. 
var result = doSomeAnalysis(JSON.parse(responseString)); 
connection.sendUTF(JSON.stringify(result)); 

Вероятно, это то, что нет никакого «тенниса» отправляется обратно на сервер, так что, даже если подключение WebSocket сохраняет свои данные вылетали, он понятия не имеет, если принимающий его конец все еще активен. Но почему мне не нужна такая же мера для моей потоковой деятельности? Он работает по тому же каналу, после того, как потоковая передача начнется, не будет возвращаться обратно от клиента (без понга) и будет продолжаться бесконечно (пока геокодирование Google не отключит меня, то есть :)).

Я полагаю, что по умозаключению в потоке должно присутствовать какое-то постоянное присутствие в потоке, и что мне нужно вручную добавить его в запрос GET, потому что я, по сути, сворачиваю пакетный ответ на поток , небольшой кусок небольшим куском, так как возвращается выход из моей функции анализа.

Прохладный. В любом случае, я думал, что оставлю это (слишком длинное) сообщение на случай, если кто-нибудь повесил трубку (каламбур!) На использование запроса GET с большими кусками данных, а затем потоковое потоковое воспроизведение через ваше сетевое соединение. Комбо работает очень хорошо, и эта проблема решена.

+0

Просто голова: если вы используете «npm websocket» и работаете с той же проблемой, ознакомьтесь с этой документацией [здесь] (https://github.com/theturtle32/WebSocket-Node/blob/master /docs/WebSocketServer.md#server-config-options) - хотя и не принимают настройки по умолчанию как должное. Установите «keepalive: true» вручную, с небольшим интервалом, чтобы выполнить ту же самую вещь, что и я выше. –

Смежные вопросы