Wat is fibjs?
fibjs is een ontwikkelingsframework voor applicatieservers dat is ontworpen voor de ontwikkeling van webbackends. Het is gebouwd op de Google V8 JavaScript-engine en gebruikt een andere gelijktijdigheidsoplossing dan traditionele callbacks. fibjs gebruikt glasvezel (glasvezel) om de bedrijfscomplexiteit te isoleren die wordt veroorzaakt door asynchrone oproepen op raamwerkniveau, waardoor de moeilijkheidsgraad van de ontwikkeling aanzienlijk wordt verminderd en prestatieproblemen worden verminderd die worden veroorzaakt door frequente asynchrone verwerking in de gebruikersruimte.
Om historische redenen wordt JavaScript voornamelijk gebruikt om de browser-UI af te handelen. UI-ontwikkeling is een typisch single-threaded, gebeurtenisgestuurd model, dus JavaScript heeft geleidelijk asynchrone verwerking als het belangrijkste programmeerparadigma gevormd.
Met het succes van JavaScript beginnen steeds meer mensen JavaScript op andere scenario's toe te passen. Tegelijkertijd zijn mensen zich er steeds meer van bewust dat asynchrone verwerking in veel scenario's niet de meest geschikte keuze is.
Terugkeer naar de natuur, agile ontwikkeling
fibjs gebruikt glasvezel op raamwerkniveau om de bedrijfscomplexiteit veroorzaakt door asynchrone oproepen te isoleren, en kapselt asynchrone I/O-verwerking in in intuïtievere synchrone oproepen. Ingenieurs hoeven alleen maar code te schrijven volgens de gebruikelijke synchrone bedrijfslogica en kunnen profiteren van het grote gemak dat asynchrone verwerking met zich meebrengt.
De volgende code is afkomstig uit de documentatie van de mysql-module:
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!');
});
});
});
});
In fibjs wordt hetzelfde werk gedaan, de code is als volgt:
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!');
Als je op zoek bent naar eenvoud, kun je de code zelfs als volgt schrijven:
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!');
Door vergelijking kunnen we duidelijk de verschillen zien die verschillende programmeerstijlen met zich meebrengen. Minder code betekent minder fouten, en met minder code wordt de logica van de code duidelijker. In dit geval zullen zowel ontwikkelings- als onderhoudswerkzaamheden hiervan profiteren.
Omarm hoge energie
Hoewel het relatief eenvoudig is om een server te schalen om de responsiviteit te verbeteren, zijn prestaties nog steeds een van de belangrijke overwegingen bij het kiezen van een ontwikkelingsframework. Met de introductie van ES7 werd asynchrone in JavaScript geïntroduceerd als een nieuw asynchrone ontwikkelingsmodel. Hoewel we genieten van de synchrone programmeerstijl die async met zich meebrengt, moeten we ook de impact ervan op de prestaties onder ogen zien.
Om de prestatieverschillen veroorzaakt door verschillende programmeerstijlen te vergelijken, kunnen we de volgende testcode gebruiken:
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();
Onder de nieuwste v8 zijn de lopende resultaten van deze code als volgt:
1
2
3async: 0.539ms
callback: 0.221ms
sync: 0.061ms
Uit de testresultaten kunnen we duidelijk zien dat wanneer async op grote schaal wordt gebruikt, de server veel tijd zal besteden aan het verwerken van de aanroepen en retourneringen van asynchrone functies. We hebben dit ook gevonden in enkele daadwerkelijke applicatietests op de server. Deze drastische prestatiedaling is echter volkomen onaanvaardbaar.
Fijs maakt daarentegen gebruik van glasvezeltechnologie, maakt optimaal gebruik van de kenmerken van de JavaScript-taal zelf en maximaliseert de superieure prestaties van de V8-motor. Ingenieurs kunnen de serverprestaties eenvoudig maximaliseren.
Kies flexibel voor paradigma's zonder te worden ontvoerd
Als u ervoor kiest om fibjs te gebruiken, betekent dit niet dat u een synchrone ontwikkelstijl moet gebruiken. In feite ondersteunt fibjs verschillende asynchrone programmeerparadigma's waarmee u bekend bent, en kan flexibel schakelen tussen synchrone en asynchrone stijlen.
Of het nu callback-functies of async zijn, ze hebben een fatale fout, namelijk besmettelijkheid. Als een functie een callback- of asynchrone functie is, moeten alle andere functies die ervan afhankelijk zijn ook callback- of asynchrone functies zijn. Bij grootschalige softwareontwikkeling zal dit leiden tot enorme ontwikkelingskosten.
Neem een eenvoudig serverontwikkelingsscenario als voorbeeld. Bij de start van het project hebben we ervoor gekozen om de sessiedata in het geheugen op te slaan, zodat we de data nu direct via synchronisatie kunnen uitlezen en opslaan, en op basis daarvan complete bedrijfsfuncties kunnen ontwikkelen. Naarmate de bedrijfsschaal groter wordt, moeten we sessiegegevens opslaan in Redis of MongoDB. Op dit moment moeten we sessiegerelateerde bewerkingen overzetten naar de asynchrone modus.
In theorie kunnen we elke functie één voor één aanpassen om ze te laten voldoen aan de vereisten van de afhankelijke functies, maar dit vereist dat we alle modules volledig begrijpen en de mogelijkheid hebben om ze aan te passen. Dit is bijna onmogelijk wanneer meerdere mensen samen ontwikkelen of modules van derden gebruiken.
Daarom moeten in alle gangbare modules zowel synchrone als asynchrone interfaces worden voorzien om de relatie tussen asynchronie en prestatie in evenwicht te brengen. Gewone ontwikkelaars kiezen er meestal voor om alleen asynchrone interfaces te bieden, wat prestatieproblemen veroorzaakt.
In fibjs kun je soortgelijke problemen eenvoudig oplossen en ongecontroleerde verspreiding van expliciete async voorkomen:
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 biedt de functie util.sync, die callback-functies of asynchrone functies kan omzetten in synchrone functies en deze rechtstreeks kan aanroepen. Op deze manier kunnen we eenvoudig modules van verschillende programmeerparadigma's integreren en de ontwikkelingskosten minimaliseren, door ze om te zetten in gesynchroniseerde paradigma's, waardoor we effectief de ramp kunnen vermijden die wordt veroorzaakt door paradigmabesmetting.
Begin met ervaren
Ben je klaar voor een geweldige ontwikkelingservaring? Laten we dus beginnen met de installatie.