Precea

Just an another blog

Optimize your nodeJS and Express apps (part1)

Optimize the system (linux / CentOS)

The first thing to do is to have an optimal OS configuration on wich we will run our apps. If the OS is not well configured, we can optimize our application as much as we want, we will not have optimal performance and it's why we will first focus on this part.

Optimize Kernel settings

Te kernel, by default, has fairly low limits on network, we will try to increase it a little.

Increase the backlog socket setting

The default setting for SOMAXCONN is 128 under CentOS as well as in most linux distribution. This setting determines the maximum number of listen() a socket can accept simultaneously. This limit is too low for exisiting server and can degrade the performance of your application if you have more simultaneous connection than this limit.

For those who say that this limit is dangerous because it can use too much memory, I would like to say that one listen, in a 64b server, use 160b in memory, with a limit of 8k, this will use only 1.25M in memory.

For the good value to be here, it will depend. Generally, a good limit is between 128 and 8192 (generally, I use a limit of 4096 on my project).

Allow the system to reuse sockect (optional)

One of the problems I have encountered is the huge number os connection in TIMEWAIT_. I have no magic solution to this. Under hard load, I still have a lot of them, but we can help the system to reuse its socket in end of life:

tcp_tw_reuse = 1
tcp_fin_timeout = 15 (in second)

By default, tcpfintimeout is 60s, this means that the kernel will wait 60 second before closing the socket if all applications already close it but we do not have a confirmation from the client.

Increase the limit of file descriptor

This is one of the most important points. On CentOS, the limit is 1024 file descriptor by application, by default. This is roughly the number of files that the application can have open at the same time, but since Linux, everything is a file, this includes the number of connection. This can be a major performance problem.

There are two way to change it: we can define it by user in the system level or for the current session. In my case, nodejs run with it user or nobody and I change the limit at the system level.

Increase the limit for the current session
ulimit -n 9999
node app.js

It's as simple as that!

Increase the limit for an user
vim /etc/security/limits.d/99-nobody
#user  soft/hard/all option    value
nobody       -       nofile    9999
Check the limit for the current process

If you want to check the limit for the current process, you must have its PID:

#  ps ax | grep node
PID  [...]  COMMAND
5699 [...] node app.js

Then we will check the limits of PID:

cat /proc/__PID__/limits
Limit                     Soft Limit           Hard Limit           Units
[...]
Max open files            9999                 9999                 files

Et voilà! We have the limit set before in place.

Optimiser votre application NodeJS + Express part1

Optimiser le système (linux / CentOS)

La première des choses est d'avoir un système optimal sur le quel rouler notre application. Si le système est mal configuré, on pourra optimiser autant que l'on veut l'application, on n'aura jamais des performances optimal, et c'est pourquoi, cela va être mon premier axe d'optimisation.

Optimiser les paramètre du Kernel

Le kernel, par défaut, possède des limites assez basse au niveau du réseau, on va tenter des les augmenter un petit peu.

Augmenter le backlog de socket pour le kernel

Par défaut, le paramètre SOMAXCONN est à 128 sous CentOS ainsi que dans la plus part des distribution linux. Se paramètre détermine le nombre maximum de listen() qu'un socket peut accepter simultanément. Cette limite est trop basse pour les serveurs actuels et peut dégrader les performances de notre application si on a plus de connection simultannée que cette limite.

Pour ceux qui disent que cette limite est dangereuse car elle peut utiliser trop de mémoire, pour un serveur 64b, chaque listen consomme 160b en mémoire, avec une valeur à 8k, cela représente seulement 1.25M.

Pour la bonne valeur à mettre ici, cela va dépendre, généralement, la bonne limite est entre 128 et 8192.

Permettre au système de réutiliser les sockets plus utilisé (optionel)

Un des problèmes que j'ai rencontré est le nombre énorme de conenction en TIMEWAIT_. J'ai pas de solution magique pour cela, sous très fort load, j'en ai encore beaucoup, par contre, ce qui peut aider le système à réutiliser ses sockets en fin de vie, les paramètres suivants peuvent être changé :

tcp_tw_reuse = 1
tcp_fin_timeout = 15 (in second)

Par défaut tcpfintimeout est à 60s, c'est à dire que le kernel va attendre jusqu'à 60s avant de fermer la connection si c'est nous qui fermons la connection et non le client.

Augmenter la limite de file descriptor

C'est l'un des points les plus importants. Sur CentOS, la limite est de 1024 file descriptor par application, par défaut. C'est en gros le nombre de fichier que l'application peut d'avoir ouvert en même temps, mais comme, sous linux, tout est fichier, cela inclue le nombre de connection. C'est l'un des principaux problèmes de performance. Pour le modifier, il y a deux moyen, soit on le défini au niveau de l'utilisateur, soit de la session en cours.

De mon bord, l'application nodejs possède soit son propre utilisateur, soit il utilise nobody, et j'augmente la limite au niveau du système.

Augmenter la limite pour la session en cours
ulimit -n 9999
node app.js

C'est aussi simple que cela.

Augmenter la limite pour un utilisateur
vim /etc/security/limits.d/99-nobody
#user  soft/hard/all option    value
nobody       -       nofile    9999
Vérifier la limite pour le processus en cours

Si vous voulez vérifier la limite pour le processus en cours, vous devez avoir son PID :

#  ps ax | grep node
PID  [...]  COMMAND
5699 [...] node app.js

Ensuite, on va voir les limites du PID :

cat /proc/__PID__/limits
Limit                     Soft Limit           Hard Limit           Units
[...]
Max open files            9999                 9999                 files

Et voilà, on a bien la limite de définie avant.

Petits changements utile pour Ghost

Coloration syntaxique

Par défaut, il n'y a pas de coloration syntaxique sur Ghost, et j'ai donc décidé d'en ajouter. Pour cela, j'aime le script Prism et c'est celui que j'ai choisit.

Télécharger le javascript et le CSS

Installer les scripts dans Ghost

  • Uploader le javascript dans : GHOST_PATH/content/themes/THEME/assets/js/
  • Uplader le CSS dans : GHOST_PATH/content/themes/THEME/assets/css/
  • Modifier le fichier de base du thème courant pour ajouter les deux fichiers GHOST_PATH/content/themes/THEME/default.hbs

Cherchez {{! Styles'n'Scripts }} et ajoutez cette ligne:

<link rel="stylesheet" type="text/css" href="/assets/css/prism.css" />  

Cherchez {{! The main JavaScript file for Casper }} et ajoutez cette ligne :

<script type="text/javascript" src="/assets/js/prism.js"></script>  
  • Et voilà ! Il ne reste plus qu'à relancer Ghost pour qu'il prenne en compte les changements.

Comment l'utiliser ?

Il suffit d'ajouter un block de code en spécifiant le language utilisé, exemple, pour du javascript :

```language-javascript
var foo = 'Hello World!';
``` 

Et voilà ce que cela donne :

var foo = 'Hello World!';  

Article complet au lieu d'un extrait sur la page d'accueil

Je préfère avoir les articles complets sur la page d'accueil au lieu de seulement un extrait, surtout que cela cause quelques problèmes d'affichage avec les block de code.

Pour ce faire, il suffit de modifier le fichier suivant :
GHOST_PATH/content/themes/THEME/index.hbs Il faut modifier {{excerpt}} par {{content}}, sauvegarder et relancer Ghost, ainsi que la classe CSS post-excerpt en post-content.

Bienvenue sur mon (nouveau) blog

Alors cette fois, je ne vais pas vous dire que je vais écrire plein d'article et tout et tout. Par contre, je pense poster plus des trucs lié à la programmation, à mes recherches du moment, ou mes passions.

A bientôt pour mon prochain article !