Что такое фибджс?
fibjs — это среда разработки серверов приложений, предназначенная для разработки веб-серверов. Он построен на движке JavaScript Google V8 и использует другое решение для параллелизма, чем традиционные обратные вызовы. fibjs использует волокно (fiber) для изоляции бизнес-сложности, вызванной асинхронными вызовами на уровне платформы, что значительно снижает сложность разработки и снижает проблемы с производительностью, вызванные частой асинхронной обработкой в пользовательском пространстве.
По историческим причинам JavaScript в основном используется для обработки пользовательского интерфейса браузера. Разработка пользовательского интерфейса — это типичная однопоточная модель, управляемая событиями, поэтому JavaScript постепенно превратил асинхронную обработку в качестве основной парадигмы программирования.
Благодаря успеху JavaScript все больше и больше людей начинают применять его в других сценариях. В то же время люди все больше осознают, что во многих сценариях асинхронная обработка — не самый подходящий выбор.
Возвращение к природе, гибкое развитие
fibjs использует волокно (fiber) на уровне платформы, чтобы изолировать сложность бизнеса, вызванную асинхронными вызовами, и инкапсулирует асинхронную обработку ввода-вывода в более интуитивно понятные синхронные вызовы. Инженерам нужно только писать код в соответствии с обычной синхронной бизнес-логикой и наслаждаться большим удобством асинхронной обработки.
Следующий код взят из документации модуля 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!');
});
});
});
});
В fibjs проделывается та же работа, код следующий:
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!');
Если вы ищете простоты, вы даже можете написать код так:
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!');
Путем сравнения мы можем ясно увидеть различия, вызванные разными стилями программирования. Меньше кода означает меньше ошибок, а с меньшим количеством кода логика кода становится более понятной. В этом случае выиграют как работы по разработке, так и сопровождению.
Примите высокую энергию
Хотя масштабировать сервер для повышения оперативности относительно легко, производительность по-прежнему остается одним из важных факторов при выборе среды разработки. С появлением ES7 асинхронность была введена в JavaScript как новая модель асинхронной разработки. Однако, хотя нам нравится стиль синхронного программирования, который дает асинхронный подход, мы также должны учитывать его влияние на производительность.
Чтобы сравнить различия в производительности, вызванные разными стилями программирования, мы можем использовать следующий тестовый код:
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();
В последней версии v8 результаты работы этого кода следующие:
1
2
3async: 0.539ms
callback: 0.221ms
sync: 0.061ms
Из результатов тестирования мы ясно видим, что при широком использовании асинхронности сервер будет тратить много времени на обработку вызовов и возвратов асинхронных функций. Мы также обнаружили это в некоторых реальных тестах серверных приложений. Однако такое резкое падение производительности совершенно неприемлемо.
Напротив, fibjs использует оптоволоконную технологию, в полной мере использует характеристики самого языка JavaScript и максимизирует превосходную производительность движка V8. Инженеры могут легко максимизировать производительность сервера.
Гибко выбирайте парадигмы, не подвергаясь похищению
Выбор использования fibjs не означает, что вам нужно использовать синхронный стиль разработки. Фактически, fibjs поддерживает различные парадигмы асинхронного программирования, с которыми вы знакомы, и может гибко переключаться между синхронным и асинхронным стилями.
Однако независимо от того, являются ли они функциями обратного вызова или асинхронными, у них есть фатальный недостаток — заразность. Если функция является функцией обратного вызова или асинхронной функцией, то все остальные функции, которые от нее зависят, также должны быть функциями обратного вызова или асинхронными функциями. При крупномасштабной разработке программного обеспечения это приведет к огромным затратам на разработку.
В качестве примера возьмем простой сценарий разработки сервера. В начале проекта мы выбрали хранение данных сеанса в памяти.На данный момент мы можем напрямую читать и хранить данные с помощью синхронизации и разрабатывать на основе этого полноценные бизнес-функции. По мере расширения масштаба бизнеса нам необходимо хранить данные сеанса в Redis или MongoDB. В настоящее время нам необходимо перевести операции, связанные с сеансом, в асинхронный режим.
Теоретически мы можем модифицировать каждую функцию одну за другой, чтобы они соответствовали требованиям зависимых функций, но для этого нам необходимо полностью понимать все модули и иметь возможность их модифицировать. Это практически невозможно, когда несколько человек разрабатывают совместно или используют сторонние модули.
Поэтому во всех общих модулях должны быть предусмотрены как синхронные, так и асинхронные интерфейсы, чтобы сбалансировать соотношение асинхронности и производительности. Обычные разработчики обычно предпочитают предоставлять только асинхронные интерфейсы, что приводит к проблемам с производительностью.
В fibjs можно легко решить подобные проблемы и избежать неконтролируемого распространения явной асинхронности:
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 предоставляет функцию util.sync, которая может преобразовывать функции обратного вызова или асинхронные функции в синхронные функции и вызывать их напрямую. Таким образом, мы можем легко интегрировать модули из разных парадигм программирования и минимизировать затраты на разработку, преобразуя их в синхронизированные парадигмы, эффективно избегая катастрофы, вызванной заражением парадигм.
Начните испытывать
Готовы ли вы получить отличный опыт разработки? Итак, начнем с установки.