Практика высокопроизводительных веб-приложений
представлять
fibjs — это высокопроизводительная среда сервера приложений, предназначенная в первую очередь для разработки веб-серверов. Он построен на движке JavaScript Google v8 и использует другое решение для параллелизма, чем традиционные обратные вызовы. fibjs использует волокна для изоляции сложностей бизнеса, вызванных асинхронными вызовами на уровне платформы, что значительно снижает сложность разработки и снижает проблемы с производительностью, вызванные частой асинхронной обработкой в пользовательском пространстве.
При разработке fibjs большое внимание уделяется производительности.Встроенные сетевые модули ввода-вывода и HTTP используют событийно-управляемую неблокирующую модель ввода-вывода, поэтому разработчики могут легко реализовывать высоконадежные серверные приложения. А поскольку нижний уровень реализован на C++, fibjs имеет очень высокую производительность и может легко справляться с высокой степенью одновременного доступа и предоставлять чрезвычайно стабильные и надежные услуги.
В то же время fibjs также поддерживает WebSocket, полнодуплексный протокол связи, основанный на протоколе TCP.Он устанавливает непрерывное соединение между браузером и сервером, обеспечивает двустороннюю передачу данных в реальном времени и может поддерживать данные. в любом формате.передача. WebSocket можно использовать для простой реализации приложений связи в реальном времени с лучшими коммуникационными эффектами.
Короче говоря, fibjs не только подчеркивает высокую производительность и высокую надежность, но также предоставляет функции связи в реальном времени, такие как WebSocket.Это среда, которая очень подходит для разработки высокоскоростных веб-приложений.
Настройка среды разработки
Прежде чем приступить к разработке fibjs, нам необходимо подготовить среду разработки. В этой главе рассказывается, как установить fibjs, как использовать инструмент fibjs для инициализации проекта и как использовать интегрированную среду разработки IDE.
Установить фибджс
Для разных операционных систем способы установки fibjs немного отличаются.
Для пользователей Linux и macOS fibjs можно установить с помощью следующей команды:
1curl -s https://fibjs.org/download/installer.sh | sh
Если вы используете macOS и используете менеджер пакетов Homebrew, вы также можете установить его с помощью следующей команды:
1brew install fibjs
Пользователям Windows необходимо загрузить установщик с официального сайта fibjs, а затем следовать инструкциям по его установке.
Создайте новый проект, используя fibjs –init.
После установки fibjs вы можете использовать инструмент fibjs для быстрого создания новых проектов. Используйте следующую команду, чтобы создать базовый шаблон проекта:
1fibjs --init
Эта команда создаст новую структуру проекта в текущем каталоге, включая package.json, который используется для хранения основной информации о проекте и информации о зависимостях.
Написание веб-приложений
Разработка веб-приложений в настоящее время является наиболее часто используемым сценарием применения fibjs. fibjs предоставляет ряд инструментов и модулей, которые помогают нам быстрее создавать веб-приложения.
Написание HTTP-сервера
- Сначала импортируйте модуль http;
- Создайте экземпляр http.Server и прослушивайте запросы.
- Сервер запускается через функцию start.
1
2
3
4
5
6const http = require('http');
const server = new http.Server(8080, (req) => {
req.response.write('Hello World!');
});
server.start();
Анализ параметров URL и тела запроса
Анализ параметров URL и тела запроса очень важен и используется в различных серверных приложениях. В fibjs параметры входящего URL-адреса могут анализироваться непосредственно через req.query, а тело запроса считывается через req.body.
1
2
3
4
5
6
7
8const http = require('http');
const server = new http.Server(8080, (req) => {
var name = req.query.get('name');
var msg = name ? `Hello ${name}!` : 'Hello world!';
req.response.write(msg);
});
server.start();
Внедрить контроль доступа к интерфейсу
Ограничение доступа пользователей через интерфейсы — очень распространенный сценарий. Ниже приведен простой пример.
1
2
3
4
5
6
7
8
9
10const http = require('http');
const server = new http.Server(8080, (req) => {
if (req.headers.get('auth') === 'ok') {
req.response.write('Hello World!');
} else {
req.response.write('Access Denied!');
}
});
server.start();
Добавить обработку маршрутизации
Маршрутизация — одна из наиболее важных концепций веб-приложения.Маршрутизация подразумевает распределение полученных запросов по процессорам в соответствии с определенными правилами. В fibjs вы можете написать свой собственный модуль маршрутизации и привязать его к http-серверу, а затем выполнить сопоставление URL-адресов и соответствующую обработку посредством настраиваемого анализа маршрутов.
1
2
3
4
5
6
7
8
9const http = require('http');
const { Router } = require('mq');
var router = new Router();
router.get('/hello/:name', function (req, name) {
req.response.write('hello, ' + name);
});
var svr = new http.Server(8080, router);
svr.start();
Приведенный выше пример также можно реализовать с помощью более простого синтаксиса:
1
2
3
4
5
6
7
8const http = require('http');
var svr = new http.Server(8080, {
'/hello/:name': function (req, name) {
req.response.write('hello, ' + name);
}
});
svr.start();
Обработка и протоколирование ошибок
В fibjs можно перехватывать логические исключения через блоки try-catch и выводить их в файлы журналов для отладки и записи; если они являются фатальными исключениями, их можно перебрасывать непосредственно в верхний фреймворк для обработки.
1
2
3
4
5
6
7
8
9
10const console = require('console');
const http = require('http');
const server = new http.Server(8080, (req) => {
try {
// ...
} catch (e) {
console.log(e.message, e.stack);
}
});
междоменный запрос
В fibjs мы можем использовать метод EnableCrossOrigin, чтобы разрешить междоменные запросы. Вот пример кода того, как создать http-сервер и разрешить междоменные запросы:
1
2
3
4
5
6
7
8const http = require('http');
const server = new http.Server(8080, (req) => {
req.response.write('Hello World!');
});
server.enableCrossOrigin(); // enable cross domain request
server.start();
В приведенном выше примере мы создали http-сервер с портом 8080. Метод EnableCrossOrigin() позволяет выполнять запросы из разных источников.
При использовании EnableCrossOrigin для разрешения междоменных запросов вы можете указать междоменные заголовки, которые разрешено получать, передав параметрallowHeaders. По умолчанию значениемallowHeaders является Content-Type.
Пример кода выглядит следующим образом:
1
2// enable "Content-Type" and "Authorization" headers in cross domain request
server.enableCrossOrigin("Content-Type, Authorization");
В приведенном выше коде значениемallowHeaders является «Content-Type, Authorization», что означает, что серверу разрешено получать два междоменных заголовка «Content-Type» и «Authorization». Если запрос содержит другие заголовки, он будет отклонен сервером.
Следует отметить, что когда мы используем EnableCrossOrigin для настройки возможности получения междоменных заголовков, нам также необходимо установить соответствующий заголовок запроса при отправке междоменных запросов, иначе он также будет отклонен сервером.
Вебсокеты
Протокол WebSocket — это полнодуплексный протокол связи, основанный на протоколе TCP. Он устанавливает бесперебойное соединение между браузером и сервером, может реализовать двустороннюю передачу данных в реальном времени и может поддерживать передачу данных в любом формате. В fibjs модуль поддержки WebSocket предоставляет соответствующие интерфейсы API, которые могут реализовать разработку сервера и клиента WebSocket.
Используйте собственный модуль WebSocket fibjs для реализации серверной части WebSocket.
На стороне сервера HTTP-запросы можно преобразовать в соединения WebSocket с помощью функции обновления. При создании объекта http-сервера вы можете использовать ws.upgrade(callback) и передать его в метод http.start() для преобразования http-запроса в WebSocket.
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
27var ws = require('ws');
var http = require('http');
var server = new http.Server(8080, {
'/ws': ws.upgrade(function(conn, req) {
console.log('a client connected.');
// listening for message events
conn.onmessage = function(evt) {
console.log('received message: ', evt.data);
// echo the message back to client
conn.send('Server: ' + evt.data);
};
// listening for close events
conn.onclose = function(code, reason) {
console.log('closed.');
};
// listening for error events
conn.onerror = function(err) {
console.log(err);
};
})
});
server.start();
В приведенном выше примере мы можем отслеживать событие сообщения, отправленное клиентом, и событие закрытия соединения между сервером и клиентом. Когда сервер получает сообщение клиента, он отправляет то же сообщение обратно клиенту. На этом этапе реализована простая двухточечная связь WebSocket.
Реализуйте взаимодействие с хранилищем данных
При использовании WebSocket для связи помимо простой отправки и получения сообщений вам также необходимо учитывать такие операции, как постоянное хранение и запрос данных. На данный момент вам необходимо использовать базу данных.Вы можете использовать модуль db, встроенный в fibjs, для взаимодействия с базой данных.
Пример кода выглядит следующим образом:
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
33var ws = require("ws");
var http = require("http");
var db = require("db");
// open a mysql connection
var mysql = db.openMySQL("mysql://root:password@localhost/dbname");
var server = new http.Server(8080, {
"/ws": ws.upgrade(function(conn, req) {
console.log("a client connected.");
// listening for message events
conn.onmessage = function(evt) {
console.log("received message: ", evt.data);
// use execute to query the data
var rs = mysql.execute("SELECT * FROM user WHERE name=?", evt.data.toString());
conn.send(JSON.stringify(rs));
};
// listening for close events
conn.onclose = function(code, reason) {
console.log("closed.");
};
// listening for error events
conn.onerror = function(err) {
console.log(err);
};
})
});
server.start();
В приведенном выше примере мы сначала использовали метод openMySQL модуля db для создания объекта подключения к базе данных MySQL mysql, а затем, прослушав сообщение от клиента, мы использовали метод выполнения для непосредственного выполнения SQL-запроса и получения записей, которые выполнить условия. Наконец, результаты запроса отправляются обратно клиенту через протокол WebSocket.
Следует отметить, что в реальной разработке необходимо хорошо выполнять обработку исключений и безопасность данных.
Подводя итог, с помощью модуля db мы можем легко и просто взаимодействовать с базой данных в сочетании с протоколом WebSocket для реализации высокопроизводительных веб-приложений в реальном времени.
Реализация клиент-серверной связи WebSocket.
На стороне клиента вы можете подключиться к серверу WebSocket, создав экземпляр WebSocket и указав URL-адрес, а затем отправлять сообщения на сервер.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24var ws = require('ws');
// create a WebSocket object and connect to ws://localhost:8080/ws
var conn = new ws.Socket('ws://localhost:8080/ws');
// listening for open events
conn.onopen = function() {
conn.send('hello');
}
// listening for message events
conn.onmessage = function(evt) {
console.log('received message:', evt.data);
}
// listening for close events
conn.onclose = function(code, reason) {
console.log('closed.');
}
// listening for error events
conn.onerror = function(err) {
console.log(err);
}
В приведенном выше клиентском коде мы создаем экземпляр WebSocket и указываем его URL-адрес.После успешного установления соединения мы можем отправлять сообщения на сервер. Когда сервер получает сообщение клиента, он отправляет то же сообщение обратно клиенту. На этом этапе реализована простая двухточечная связь WebSocket.
Преимущества и сценарии использования WebSocket
Протокол WebSocket имеет типичную модель двусторонней связи, позволяющую серверу активно передавать данные клиенту.Он часто используется для реализации чата, онлайн-игр и других случаев, требующих работы в режиме реального времени и высокой оперативности. По сравнению с другими протоколами передачи протокол WebSocket имеет следующие преимущества:
• Высокая производительность в реальном времени, поддержка двусторонней связи • Простая спецификация протокола, простота в использовании • Возможность обработки большого количества одновременных подключений • Поддерживает длинные соединения, сокращая время передачи по сети
Наиболее распространенные сценарии использования WebSocket включают веб-чат, игровые сражения, онлайн-воспроизведение и обмен мгновенными сообщениями.
Подводя итог, можно сказать, что с помощью модуля поддержки WebSocket его очень просто реализовать, и разработчики могут быстро создавать свои собственные веб-приложения.
модульный тест
Среды тестирования и методы тестирования
В процессе разработки программного обеспечения тестирование является очень важным звеном, и модульное тестирование является важной его частью. Модульное тестирование может эффективно проверить, соответствует ли код дизайну и требованиям, и избежать ошибок, возникающих при изменении кода. Вообще говоря, принцип модульного тестирования заключается в проверке каждой функции и метода, чтобы убедиться в правильности входных и выходных данных каждой функции и метода.
Платформа тестирования — это база кода, используемая для написания, запуска и проверки тестовых примеров. Она обеспечивает управление тестовыми примерами, выполнение функций и создание отчетов. В JavaScript и Node.js популярные среды модульного тестирования включают Mocha, Jest и Jasmine. В fibjs также есть собственная среда тестирования — тестовый модуль.
В процессе модульного тестирования обычно используемые методы тестирования включают тестирование «черного ящика» и тестирование «белого ящика».
Тестирование «черного ящика» — это метод тестирования, который учитывает только входные и выходные данные функции, не принимая во внимание детали реализации внутри функции. Тестирование «черного ящика» основано на анализе требований и проектных спецификациях.Посредством анализа и выполнения тестовых примеров определяется, есть ли в программе логические ошибки, граничные ошибки, проблемы безопасности и т. д. Его преимуществом является простота процесса тестирования и надежность результатов, а недостатком — то, что тест не может охватить все пути программы.
Тестирование белого ящика — это метод тестирования, который учитывает детали внутренней реализации функции, включая условные операторы, операторы цикла, рекурсию и покрытие кода. Эти тесты могут выявить возможные проблемы во взаимодействии общих данных и кода. Преимущество тестирования «белого ящика» заключается в том, что оно может охватывать все пути программы, а недостаток — в том, что процесс тестирования более сложен, а на результаты тестирования влияют среда и методы реализации.
Написание тестовых случаев с использованием тестового модуля
В fibjs мы можем использовать тестовый модуль для написания тестовых примеров для веб-сервера. Вот простой пример:
1
2
3
4
5
6
7
8
9
10
11
12
13
14var test = require('test');
test.setup();
var http = require('http');
describe('Web server test', () => {
it('should return hello world', () => {
var r = http.get('http://localhost:8080/hello');
assert.equal(r.statusCode, 200);
assert.equal(r.data.toString(), 'Hello World');
});
});
test.run();
В этом примере мы используем функции описания и it для определения тестового модуля и тестового примера соответственно, а также используем функцию утверждения для проверки утверждений.
В функции описания мы можем определить несколько ИТ-функций для тестирования различных сценариев соответственно. В каждой функции it мы можем использовать функцию http.get для имитации HTTP-запроса GET, получения ответа на запрос и выполнения проверки утверждений, например, AssertTrue и AssertEqual.
Написав тестовые примеры, вы сможете эффективно проверить корректность функций и модулей, обеспечить качество продукта, а также повысить удобство сопровождения кода.
Горячее обновление
Горячее обновление означает обновление кода сервера без остановки службы. В процессе разработки программы для быстрой итерации часто требуются корректировки кода и новые функции. Используя горячее обновление, вы можете использовать новый код для более эффективного выполнения итерации без остановки службы.
В fibjs мы можем использовать модуль SandBox для обеспечения плавных горячих обновлений. Модуль SandBox может обеспечить безопасную среду выполнения и моделировать глобальные переменные и другие функции. Для конкретной реализации, пожалуйста, обратитесь к следующим шагам:
- Загрузите файлы кода, которые необходимо обновить (например, web.js).
- С помощью SandBox создайте новый модуль безопасности, загрузите в него web.js и сгенерируйте модуль безопасности. Перемонтируйте обработчик запущенного сервиса через сгенерированный модуль безопасности.
- Сервер продолжает обрабатывать предыдущие запросы, а новые запросы будут монтироваться на новом обработчике.
Ниже приведен пример кода, который использует модуль SandBox для реализации плавных горячих обновлений:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16const fs = require('fs');
const http = require('http');
const { SandBox } = require('vm');
let FILE_PATH = './web.js';
let handler = new SandBox().require(FILE_PATH).handler;
const server = new http.Server(8080, handler);
server.start();
fs.watch(FILE_PATH, (event, filename) => {
handler = new SandBox().require(FILE_PATH).handler;
server.handler = handler;
console.log(`[${new Date().toLocaleString()}] server reloaded.`);
});
В этом коде мы сначала загружаем код в web.js при запуске программы, затем создаем экземпляр SandBox и загружаем в него код. После этого мы создали новый HTTP-сервер и использовали методы обработчика для обработки запроса.
В коде мы используем fs.watch для отслеживания изменений в файле web.js. Как только файл изменится, мы перезагружаем код и обновляем реализацию в обработчике.
Оптимизация производительности
В процессе разработки нам часто приходится сталкиваться с проблемами производительности. Оптимизация кода и повышение производительности — одни из важнейших навыков для разработчиков. В fibjs мы можем использовать CPU Profiler, который поможет нам проанализировать рабочее состояние программы и оптимизировать код.
В fibjs вам нужно использовать только параметр командной строки --prof, чтобы запустить fibjs и запустить профилировщик ЦП (интервал по умолчанию — 1000 мс). Если вам нужен более точный анализ журнала, вы можете использовать параметр --prof-interval, чтобы установить интервал журнала. Например:
1
2$ fibjs --prof test.js # 启动 CPU Profiler,默认以 1000ms 为间隔
$ fibjs --prof --prof-interval=10ms test.js # 启动 CPU Profiler,以 10000us(即 10ms)为间隔
Когда fibjs завершит работу, в текущем каталоге будет создан каталог с именем исходного файла. Этот каталог содержит файл журнала и некоторые вспомогательные файлы. Имя файла журнала по умолчанию — fibjs-xxxx.log, где xxxx — это временная метка. Вы можете использовать опцию --log, чтобы указать имя файла журнала. На этом этапе вы можете --prof-process
обработать сгенерированные журналы, используя:
1fibjs --prof-process fibjs-xxxx.log prof.svg
После завершения операции используйте браузер, чтобы открыть prof.svg, чтобы просмотреть график пламени этого журнала: вы можете нажать, чтобы просмотреть полноразмерное изображение. В полноразмерном изображении вы можете использовать мышь, чтобы просмотреть более подробную информацию. информация: проф.svg .
В сгенерированном графе пламени каждый цветовой блок представляет точку записи. Чем длиннее цветовой блок, тем больше раз он записывается; каждая линия представляет собой слой стека вызовов, и чем больше слоев, тем больше слоев вызывается; вызовы Стек располагается в перевернутом виде, чем ниже цветовой блок, тем оригинальнее функция.
Существует два типа цветных блоков: красный и синий. В профилировщике fibjs красный цвет представляет операции JavaScript, а синий — операции ввода-вывода или собственные операции. В зависимости от проблемы, которую вам нужно решить, области, на которых вам нужно сосредоточиться, будут различаться. Например, если вам нужно решить проблему высокой загрузки ЦП, вам нужно обратить внимание на блоки красного цвета.Если ваше приложение имеет низкую загрузку ЦП, но медленный отклик, вам нужно обратить внимание на блоки синего цвета. Чем больше цветовой блок вверху, тем больше внимания и оптимизации он требует.
Мы можем попытаться настроить функции, которые потребляют больше ресурсов ЦП, реализовать асинхронный ввод-вывод и т. д. или оптимизировать код при написании.
Развертывание и онлайн
Чтобы наш проект мог работать в производственной среде, нам необходимо его скомпилировать и развернуть. Здесь мы покажем, как использовать файл package.json для настройки компиляции и развертывания.
В проекте мы можем использовать package.json для управления зависимостями проекта, настройки компиляции и развертывания. В качестве примера возьмем простой пример package.json:
1
2
3
4
5
6
7{
"name": "my-project",
"version": "1.0.0",
"dependencies": {
"fib-pool": "^1.0.0"
}
}
Когда нам нужно скомпилировать и развернуть проект, нам нужно всего лишь войти в каталог проекта в терминале и выполнить следующую команду:
1fibjs --install
Эта команда автоматически установит модули, от которых зависит проект. После этого мы можем запустить проект, используя следующую команду:
1fibjs app.js