Git Product home page Git Product logo

node-toobusy's Introduction

Build Status

Is Your Node Process Too Busy?

toobusy-js is a fork of lloyd's node-toobusy that removes native dependencies in favor of using the unref introduced in node 0.9.1.

This package is a simpler install without native dependencies, but requires node >= 0.9.1.

Node-Toobusy

What happens when your service is overwhelmed with traffic? Your server can do one of two things:

  • Stop working, or...
  • Keep serving as many requests as possible

This library helps you do the latter.

How it works

toobusy polls the node.js event loop and keeps track of "lag", which is long requests wait in node's event queue to be processed. When lag crosses a threshold, toobusy tells you that you're too busy. At this point you can stop request processing early (before you spend too much time on them and compound the problem), and return a "Server Too Busy" response. This allows your server to stay responsive under extreme load, and continue serving as many requests as possible.

installation

npm install toobusy-js

usage

var toobusy = require('toobusy-js'),
    express = require('express');

var app = express();

// middleware which blocks requests when we're too busy
app.use(function(req, res, next) {
  if (toobusy()) {
    res.send(503, "I'm busy right now, sorry.");
  } else {
    next();
  }
});

app.get('/', function(req, res) {
  // processing the request requires some work!
  var i = 0;
  while (i < 1e5) i++;
  res.send("I counted to " + i);
});

var server = app.listen(3000);

process.on('SIGINT', function() {
  server.close();
  // calling .shutdown allows your process to exit normally
  toobusy.shutdown();
  process.exit();
});

tunable parameters

The library exposes a few knobs:

maxLag - This number represents the maximum amount of time in milliseconds that the event queue is behind, before we consider the process too busy. interval - The check interval for measuring event loop lag, in ms.

var toobusy = require('toobusy-js');

// Set maximum lag to an aggressive value.
toobusy.maxLag(10);

// Set check interval to a faster value. This will catch more latency spikes
// but may cause the check to be too sensitive.
toobusy.interval(250);

// Get current maxLag or interval setting by calling without parameters.
var currentMaxLag = toobusy.maxLag(), interval = toobusy.interval();

toobusy.onLag(function(currentLag) {
  console.log("Event loop lag detected! Latency: " + currentLag + "ms");
});

The default maxLag value is 70ms, and the default check interval is 500ms. This allows an "average" server to run at 90-100% CPU and keeps request latency at around 200ms. For comparison, a maxLag value of 10ms results in 60-70% CPU usage, while latency for "average" requests stays at about 40ms.

These numbers are only examples, and the specifics of your hardware and application can change them drastically, so experiment! The default of 70 should get you started.

Events

As of 0.5.0, toobusy-js exposes an onLag method. Pass it a callback to be notified when a slow event loop tick has been detected.

references

There is nothing new under the sun. (Ecclesiastes 1:9)

Though applying "event loop latency" to node.js was not directly inspired by anyone else's work, this concept is not new. Here are references to others who apply the same technique:

license

WTFPL

node-toobusy's People

Contributors

aheckmann avatar davglass avatar flentini avatar gigablah avatar jacobmarble avatar lloyd avatar mnahkies avatar speier avatar strml avatar timotheeg avatar uberesch avatar vendethiel avatar waldyrious avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-toobusy's Issues

Informational rather than issue

Before switching from the C++ tooBusy version, I wanted to understand the performance of this JS version. I ran timing tests using process.hrtime and observed that the JS version was 2-3x faster than the native version. I assume this is probably due to context switch costs for c++.

As a side effect, installs are much faster.

Thanks for this.

onLag firing threshold

if the threshold is not specified, the onLag callback is called every 0ms, which I think it's misleading since there's no actual lag. Shouldn't be the default be equal to maxLag?

start() never called unless interval is explicitly set

I could be missing something here, but it seems to me that the start() function is never called and therefore toobusy never starts monitoring unless one specifically sets interval with a call such as:

toobusy.interval(500);

I am trying to switch from the lloyd/node-toobusy version to this fork. After running
npm install toobusy-js
and changing my require statement to
var toobusy = require('toobusy-js');
I was unable to get any lag values other than 0. After a little digging it seems to me that if you don't call
interval with an explicit value start() is never called.

Tests failing on 0.11+

$ node -v
v0.10.40
$ npm test

> [email protected] test /git/oss/node-toobusy
> mocha tests


  ․․․․․․․․․lag 59 currentLag 19.666666666666664
․lag 56 currentLag 18.666666666666664
․․․․lag 54 currentLag 54
․lag 53 currentLag 2.6500000000000004
lag 53 currentLag 5.1675
lag 53 currentLag 7.559125000000001
lag 53 currentLag 9.83116875
lag 53 currentLag 11.9896103125
lag 53 currentLag 14.040129796875
$ node -v
v0.11.16
$ npm test

> [email protected] test /git/oss/node-toobusy
> mocha tests

child_process: customFds option is deprecated, use stdio instead.

  ․․․․․․․․․lag 15 currentLag 5
lag 102 currentLag 37.333333333333336
․lag 107 currentLag 35.666666666666664
․․․․lag 58 currentLag 58
․lag 55 currentLag 2.75
lag 3 currentLag 2.7624999999999997
lag 57 currentLag 5.474375
lag 0 currentLag 5.20065625
lag 1 currentLag 4.990623437499999
lag 61 currentLag 7.791092265625
lag 3 currentLag 7.55153765234375
․․

  ✖ 2 of 17 tests failed:

  1) smoothingFactor should allow no dampening:
     AssertionError: expected 2 to equal 3

  2) smoothingFactor should respect larger dampening factors:
     Error: timeout of 2000ms exceeded

toobusy() should return true after a little load: Error: timeout of 2000ms exceeded

Tested with node versions, v0.10.36, v0.11.15, and 0.12 on OS X. Looks like travis-ci is unhappy as well with the same error.

  ✖ 1 of 6 tests failed:

  1) toobusy() should return true after a little load:
     Error: timeout of 2000ms exceeded
      at null.<anonymous> (/private/tmp/node-toobusy/node_modules/mocha/lib/runnable.js:161:14)
      at Timer.listOnTimeout (timers.js:109:15)

Documentation may be slightly misleading

The following line in the readme

// set maximum lag to an aggressive value 
require('toobusy-js').maxLag(10);

suggests that you can do this:

var toobusy = require( 'toobusy-js' ).maxLag(10);

which you cannot, as it predictably throws TypeError: number is not a function.

You must break it up into two method calls:

// set maximum lag to an aggressive value 
var toobusy = require('toobusy-js');
toobusy.maxLag(10);

How to test in development phase?

I tried executing this mock route

//TEST if this works
//Create this route and execute it.
router.get('/mock', function(req,res){
  // processing the request requires some work! 
  var i = 0;
  while (i < 1e5) i++;
  res.send("I counted to " + i);
});

but documented setup, but i never get toobusy() to be true. I tried opening in multiple tables and requesting same or different routes. The process ID simply breaks.

How to confirm if this works in development?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.