Requesting Elasticsearch from Node times out - javascript

I am setting up a simple Node.js REST service to interface with Elasticsearch, using the official Javascript client. I'm running this code locally, but the cluster is located remotely. When I go trough the browser, with the _head plugin, I can connect ES and query with no problem. However, doing so via the Javascript client times out all requests. I set up the ElasticSearch object, but sending any request to it simply doesn't work. I don't think it's a network issue, because I can access ES trough the browser. This is how I request something, a very basic get:
var elasticsearch = require("elasticsearch");
var es = new elasticsearch.Client({
host: "https://my-address:9200/", // also tried without protocol part and trailing slashes
log: "error",
sniffOnStart: true
});
es.get({
index: "things",
type: "someThing",
id: "42"
}).then(doSomeStuff, handleStuffFailed);
This fails with a simple error message Errror: Request timeout after 30000ms.
Am I missing something here? I've read trough the client docs, and this seems like the basic "hello world" for the client.

Try extending the requestTimeout parameter when instantiating the ES Client.
client = new elasticsearch.Client({
host : 'http://localhost:9200',
requestTimeout: 60000
});
I had a long-running process which took just under 10 minutes. By making the requestTimeout value 60000 (10 mins) the process could complete without timing out.

We also had this issue on QBox because of sniffOnStart.
Try with this config:
var es = new elasticsearch.Client({
host: "my-address:9200",
log: "trace",
sniffOnStart: true
});
You'll see that the added nodes ip are the private ip.
On our side, we decided to disable the sniffing and add manually the array of public node host addresses like this:
var es = new elasticsearch.Client({
hosts: ["my-address1:9200", "my-address2:9200", "my-address3:9200"],
log: "error"
});

Regarding timeouts in elastic search, you need to differentiate between two types of timeouts:
Initialization timeout: When you initialize ES: requestTimeout, pingTimeout both of which defaults to 30000ms. Read more: Configuration documentation in elastic search documentation
Operation-based timeouts: Many operations such as bulk, create, delete, index can set timeout too. Say if you have a huge bulk object to insert, you can just set operation-based timeouts: Elastic Search documentations
You should know that operation-based timeouts overwrite the initializationRequestTimeout.

Check here regarding this issue: https://github.com/elastic/elasticsearch-js/issues/186
I guess we need to use the requestTimeout variable as mentioned above.

Check following items if you see
Discover: Request Timeout after 30000ms
Make sure Elasticsearch CPU/Memory is not chocking
If there is a lot of data for query window then it is possible that request
times out within 30000ms
Increase timeout for kibana in kibana.yml --> elasticsearch.requestTimeout:
120000
Restart kibana service
Decrease ammount of data loaded by kibana dashboard
discover:sampleSize under Management - Advanced settings --> Change the
value accordingly
If there is any Load Balancer in between then increase timeout settings
from LB as well.

If you're running more than one node per server, try locking down the number of processors that each jvm gets access to. we had this problem and doing this fixed it. We think one node was using too much system resources and it would cause the other node on the same server to be slow to respond to the master node when queried for status.

Related

Apollo GraphQL keeps receiving requests with no queries or mutations being made

I was learning GraphQL and about to finish the tutorial and this never happened before.
The problem is that the GraphQL server keeps receiving requests after opening GraphQL Playground in the browser even though no query or mutation is made.
I see these sort of responses being returned by the server:
{
"name":"deprecated",
"description":"Marks an element of a GraphQL schema as no longer supported.",
"locations":[
"FIELD_DEFINITION",
"ENUM_VALUE"
],
"args":[
{
"name":"reason",
"description":"Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted using the Markdown syntax (as specified by [CommonMark](https://commonmark.org/).",
"type":{
"kind":"SCALAR",
"name":"String",
"ofType":null
},
"defaultValue":"\"No longer supported\""
}
]
}
This is expected behavior.
GraphQL Playground issues an introspection query to your server. It uses the result of that query to provide validation and autocompletion for your queries. Playground will send that query to your server repeatedly (every 2 seconds by default) so that if your schema changes, these changes can be immediately reflected in the UI (although there's an issue with this feature at the moment).
You can adjust the relevant settings (click on the settings icon in the top right corner of the Playground UI) to either change the polling frequency or turn it off entirely:
'schema.polling.enable': true, // enables automatic schema polling
'schema.polling.endpointFilter': '*localhost*', // endpoint filter for schema polling
'schema.polling.interval': 2000, // schema polling interval in ms
However, the behavior you're seeing is only related to Playground so it's harmless and won't impact any other clients connecting to your server.

Redis ETIMEDOUT error after some time of connection

Overview
On two separate Azure instances, on first one node.js servers are running and they connect to single node redis server running on second instance and node.js is trying to keep active connection with redis. Node Redis module is being used to store and retrieve data in redis and socket.io-emitter module is used to allow different servers to send messages based on collective connectivity of clients.
Problem
After the initial connection is done after sometime (sporadic)the connection freezes and finally crashes with ETIMEDOUT error being thrown from all servers.
What have I tried.
i. Added socket_keepalive first and then together with socket_initialdelay
const redis = require('redis');
let options = {socket_keepalive : true, socket_initialdelay : 200000};
global.client = redis.createClient(port, host, options);
ii. With socket.io-emitter module tried initialising it with new redis object using node redis module itself but the notifications stopped working after that so retracted back to the same thing.
This stopped the notification to devices individually
let options = {socket_keepalive : true, socket_initialdelay : 200000};
let redis_socket = require('redis');
let pub = redis_socket.createClient(port, host, options);
let ioz = require('socket.io-emitter')(pub);
*Obviously the timed out issue exists with the working method.
iii. On redis's server the timeout config is set at 0 and tcpdelay was 300 seconds but we tried changing it to 0 (tcpdelay) but still the problem persists.
It definitely breaks my head because same piece of code works in another environment but what is causing this is still a mystery, after investigating a bit more I realised that the clients connected (available with monitor command) drops after some time and hence etimedout error is thrown.
Same redis machine is also used for caching and it is working without any issue.
Looks like you might be hitting the TCP idle timeout of 4 minutes.
According the self-documented config for Redis 3.2, the value for tcp-keepalive has to be non-zero for it to work. So, you might want to set a value like 120 (240 / 2) instead and try again.

Keeping Web Socket Server Alive

Zup coders. I've implemented a simple website that uses Web Sockets PHP (Consik Yii2 solution: https://github.com/consik/yii2-websocket) vs JS (Html5).
Everything is working fine, I only have one issue with my solution, making sure the server is always alive.
I though about saving the WebSocket Instance into Cache and throw a cron that checks the state of the instance. I installed memcached and found out that i can´t save a serialized version of the WebSocket Server instance. ¿Is this a good solution? ¿Would Redis Caché fix this?
I also thought about using client side JS to react to "Error during WebSocket handshake: Unexpected response code: 200" but i can't seem to get it working. I also don't like making the URL that starts websockets public.
Ex:
connect = function(){
websocket = new WebSocket(webSocketURL);
websocket.onerror = function(){
$.get( "/startWebSocketServer",
function(data){
connect();
}
);
};
};
connect();
Thanks!
I think that as matter of fact you need a process supervisor who takes care to "supervise" your server process and do actions in response of process/system events like crash, restart etc..
There are several solutions for each case (standard OS implementations, personal preferences, fit your need), here a list http://without-systemd.org/wiki/index.php/Init , Service managers section could best fit your needs.
Supervisord is easy to setup and configure, it could be a good start thanks to a good bunch of examples around the net.
Solution 1: using a cache could not be the most orthodox way to implement a custom-made supervisor.
Solution 2: is legit as long as it informs user about a problem, the call to an exposed endpoint to start a service IMHO could be a security flaw.

Forever-agent in request.js - how to check if it's working

recently, external server(REST API) told me to use Keep-alive for my request. That's great, since I use request.js(node 8) I found "forever" option:
forever - set to true to use the forever-agent Note: Defaults to http(s).Agent({keepAlive:true}) in node 0.12+
To test if it's working I created my own server in Node8 using Koa.js and Node script where I create array of 100 GET request to my server and after that, I Promise.all them.
However, I don't how can I check if it's using the same agent, if it's working correctly.
Do you have any ideas, how from client(or server) point of view I can check that?
Is keep-alive enough proof that all request for certain domain are using the same agent in 1 Node.js process?
On the client, you can try to capture the socket which is used to send the request using the socket event. You can verify that they are using the same sockets on the client.
req.on("socket", function (socket) {
//if saved socket is empty save it
//else check if its using the saved socket
}

PHP minimal working example of Web Sockets

I'm trying to determine how to setup a web socket for the first time ever so a working minimal example with static variables (IP address for example instead of getservbyname) will help me understand what is flowing where.
I want to do this the right way so no frameworks or addons for both the client and the server. I want to use PHP's native web sockets as described here though without over-complicating things with in-depth classes...
http://www.php.net/manual/en/intro.sockets.php
I've already put together some basic JavaScript...
window.onload = function(e)
{
if ('WebSocket' in window)
{
var socket = new WebSocket('ws://'+path.split('http://')[1]+'mail/');
socket.onopen = function () {alert('Web Socket: connected.');}
socket.onmessage = function (event) {alert('Web Socket: '+event.data);}
}
}
It's the PHP part that I'm not really sure about. Presuming we have a blank PHP file...
If necessary how do I determine if my server's PHP install has this socket functionality already available?
Is the request essentially handled as a GET or POST request in
example?
Do I need to worry about the port numbers? e.g. if
($_SERVER['SERVER_PORT']=='8080')
How do I return a basic message on the initial connection?
How do I return a basic message say, five seconds later?
It's not that simple to create a simple example, I'm afraid.
First of all you need to check in php configuration if the server is configured for sockets with the setting enable-sockets
Then you need to implement (or find) a websocket server that at least follows the Hybi10 specification (https://datatracker.ietf.org/doc/html/draft-ietf-hybi-thewebsocketprotocol-10) of websockets. If you find the "magic number" 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 in the code for the header, you can be sure it does follow at least Hybi06 ...
Finally, you need to have access to an admin console on the server in order to execute the PHP websocket server using php -q server.php
EDIT: This is the one I've been using a year ago ... it might still work as expected with current browsers supporting Websockets: http://code.google.com/p/phpwebsocket/source/browse/trunk/+phpwebsocket/?r=5

Categories