Qu’est-ce que le fibjs ?
fibjs est un framework de développement de serveur d'applications conçu pour le développement de backend Web. Il est construit sur le moteur JavaScript Google V8 et utilise une solution de concurrence différente de celle des rappels traditionnels. fibjs utilise la fibre (fibre) pour isoler la complexité métier causée par les appels asynchrones au niveau du framework, réduisant ainsi considérablement la difficulté de développement et réduisant les problèmes de performances causés par un traitement asynchrone fréquent dans l'espace utilisateur.
Pour des raisons historiques, JavaScript est principalement utilisé pour gérer l'interface utilisateur du navigateur. Le développement de l'interface utilisateur est un modèle typique piloté par des événements à thread unique, de sorte que JavaScript a progressivement formé le traitement asynchrone comme principal paradigme de programmation.
Avec le succès de JavaScript, de plus en plus de personnes commencent à appliquer JavaScript à d'autres scénarios. Dans le même temps, les gens sont de plus en plus conscients que dans de nombreux scénarios, le traitement asynchrone n’est pas le choix le plus approprié.
Retour à la nature, développement agile
fibjs utilise la fibre (fibre) au niveau du framework pour isoler la complexité métier causée par les appels asynchrones et encapsule le traitement des E/S asynchrones dans des appels synchrones plus intuitifs. Les ingénieurs n'ont qu'à écrire du code selon la logique métier synchrone habituelle et profiter de la grande commodité apportée par le traitement asynchrone.
Le code suivant est extrait de la documentation du module mysql :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32conn.beginTransaction(err => {
if (err) {
throw err;
}
conn.query('INSERT INTO posts SET title=?', title,
(error, results, fields) => {
if (error) {
return conn.rollback(() => {
throw error;
});
}
var log = 'Post ' + results.insertId + ' added';
conn.query('INSERT INTO log SET data=?', log,
(error, results, fields) => {
if (error) {
return conn.rollback(() => {
throw error;
});
}
conn.commit((err) => {
if (err) {
return conn.rollback(() => {
throw err;
});
}
console.log('success!');
});
});
});
});
Dans fibjs, le même travail est fait, le code est le suivant :
1
2
3
4
5
6conn.trans(() => {
var result = conn.execute('INSERT INTO posts SET title=?', title);
var log = 'Post ' + results.insertId + ' added';
conn.execute('INSERT INTO log SET data=?', log);
});
console.log('success!');
Si vous recherchez la simplicité, vous pouvez même écrire le code comme ceci :
1
2
3
4conn.trans(() => conn.execute('INSERT INTO log SET data=?',
'Post ' + conn.execute('INSERT INTO posts SET title=?', title).insertId +
' added'));
console.log('success!');
Grâce à la comparaison, nous pouvons clairement voir les différences apportées par les différents styles de programmation. Moins de code signifie moins d’erreurs, et avec moins de code, la logique du code devient plus claire. Dans ce cas, les travaux de développement et de maintenance en bénéficieront.
Adoptez la haute énergie
Bien qu'il soit relativement facile de faire évoluer un serveur pour améliorer sa réactivité, les performances restent l'une des considérations importantes lors du choix d'un framework de développement. Avec l'introduction d'ES7, l'async a été introduit dans JavaScript en tant que nouveau modèle de développement asynchrone. Cependant, même si nous apprécions le style de programmation synchrone apporté par l’async, nous devons également faire face à son impact sur les performances.
Afin de comparer les différences de performances apportées par différents styles de programmation, nous pouvons utiliser le code de test suivant :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39var count = 1000;
async function test_async(n) {
if (n == count)
return;
await test_async(n + 1);
}
function test_callback(n, cb) {
if (n == count)
return cb();
test_callback(n + 1, () => {
cb();
});
}
function test_sync(n) {
if (n == count)
return;
test_sync(n + 1);
}
async function test() {
console.time("async");
await test_async(0);
console.timeEnd("async");
console.time("callback");
test_callback(0, () => {
console.timeEnd("callback");
});
console.time("sync");
test_sync(0);
console.timeEnd("sync");
}
test();
Sous la dernière v8, les résultats d'exécution de ce code sont les suivants :
1
2
3async: 0.539ms
callback: 0.221ms
sync: 0.061ms
D'après les résultats des tests, nous pouvons clairement voir que lorsque l'async est largement utilisé, le serveur passera beaucoup de temps à traiter les appels et les retours des fonctions async. Nous avons également constaté cela dans certains tests d'applications côté serveur. Cependant, cette baisse drastique des performances est totalement inacceptable.
En revanche, fibjs utilise la technologie fibre, tire pleinement parti des caractéristiques du langage JavaScript lui-même et maximise les performances supérieures du moteur V8. Les ingénieurs peuvent facilement optimiser les performances du serveur.
Choisissez des paradigmes avec flexibilité sans vous faire kidnapper
Choisir d'utiliser fibjs ne signifie pas que vous devez utiliser un style de développement synchrone. En fait, fibjs prend en charge divers paradigmes de programmation asynchrone que vous connaissez et peut basculer de manière flexible entre les styles synchrone et asynchrone.
Cependant, qu’il s’agisse de fonctions de rappel ou asynchrones, elles présentent un défaut fatal, qui est la contagiosité. Si une fonction est une fonction de rappel ou asynchrone, alors toutes les autres fonctions qui en dépendent doivent également être des fonctions de rappel ou asynchrones. Dans le cadre du développement de logiciels à grande échelle, cela entraînera des coûts de développement énormes.
Prenons comme exemple un simple scénario de développement de serveur. Au début du projet, nous avons choisi de stocker les données de session en mémoire, à ce stade, nous pouvons directement lire et stocker les données par synchronisation, et développer des fonctions métier complètes sur cette base. À mesure que l'échelle de l'entreprise s'étend, nous devons stocker les données de session dans Redis ou MongoDB. À ce stade, nous devons passer les opérations liées à la session en mode asynchrone.
En théorie, nous pouvons modifier chaque fonction une par une pour les rendre conformes aux exigences des fonctions dépendantes, mais cela nécessite de bien comprendre tous les modules et d'avoir la capacité de les modifier. Cela est presque impossible lorsque plusieurs personnes développent en collaboration ou utilisent des modules tiers.
Par conséquent, dans tous les modules courants, des interfaces synchrones et asynchrones doivent être fournies pour équilibrer la relation entre asynchrone et performances. Les développeurs ordinaires choisissent généralement de fournir uniquement des interfaces asynchrones, ce qui entraîne des problèmes de performances.
Dans fibjs, vous pouvez facilement résoudre des problèmes similaires et éviter la propagation incontrôlée d'async explicites :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17var util = require('util');
function session_get(sid) {
return sdata;
}
async function async_session_get(sid) {
return sdata;
}
function callback_session_get(sid, cb) {
cb(null, sdata);
}
data = session_get(sid);
data = util.sync(async_session_get)(sid);
data = util.sync(callback_session_get)(sid);
fibjs fournit la fonction util.sync, qui peut convertir des fonctions de rappel ou des fonctions asynchrones en fonctions synchrones et les appeler directement. De cette façon, nous pouvons facilement intégrer des modules de différents paradigmes de programmation et minimiser les coûts de développement, en les transformant en paradigmes synchronisés, évitant ainsi efficacement le désastre causé par la contagion des paradigmes.
Commencez à expérimenter
Êtes-vous prêt à vivre une belle expérience de développement ? Alors commençons par l’installation.