Ускорение серверной разработки

от автора

Всем привет! Пишу свою первую статью — не судите строго 🙂

Сегодня хочу рассказать вам о своём проекте, а точнее показать его в деле. Надеюсь, вам будет интересно!

Введение

Netter — инструмент для быстрого и лёгкого поднятия серверов. Он поддерживает следующий функционал:

  • Запуск HTTP / HTTPS серверов;

  • Тонкая настройка логики обработки на каждый маршрут с помощью язык описания маршрутов (RDL). Используется собственный интерпретатор;

  • Поддержка кастомных плагинов для их последующего использования в RDL. Плагины пишутся на Rust с использованием специального крейта для облегчения разработки

Проект создан для разработчиков, которым надоело писать большой код для запуска простых/средних по сложности серверов

Route Definition Language

Route Definition Language (RDL) — интерпретируемый язык для описания маршрутов и серверной логики.

Синтаксис

config {     type = "http"; // тип сервера     host = "127.0.0.1"; // ip адрес, по которому будет доступен сервер     port = 8080; // порт сервера }; // после блоков ';' обязательна  import "absolute/path/to/file.dll" as plugin_alias; // absolute/path/to/file.dll - абсолютный путь до динамической библиотеки .dll или .so // plugin_alias - алиас для плагина. Будет использован для доступа к функциям из плагина  global_error_handler(e) { // глоабльный обработчик ошибок.                           // здесь будут все ошибки, которые перехватил '?',                           // но локальный обработчик не был указан     Response.body("Global error: "+ e);     Response.status(500);     Response.send(); };  route "/" GET { // ждём запросы на "/" по запросу GET     val body = Request.body()?; // получаем тело запроса     // '?' перехватывает ошибки     if (body == "empty") {         Response.body("Body is empty!"); // ставим тело ответа         Response.status(400); // ставим статус ответа         Response.send(); // отправляем ответ     };     Response.body(body + "!empty"); // конкатенация строк     Response.send(); // 200 OK } onError(e) { // локальный обработчик ошибок. Если Request.body()? завершится ошибкой,                // кодд перейдёт сюда                // локальные обработчики имеют приоритет над глобальными     Response.status(500);     Response.body(e); // ставим тело ответа с текстом ошибки     Response.send(); };

Ключевые слова

Язык имеет следующие ключевые слова:

  • route — объявление маршрута;

  • GET, POST, PUT и т.д. — тип запроса;

  • global_error_handler — объявление глобального обработчика ошибок;

  • onError — объявление локального обработчика

Более подробно с документацией языка (объекты, функции, ключевые слова, обработчики ошибок…) можно в репозитории.

Обработка ошибок

Обработка ошибок — ключевой элемент написания кода. Язык предоставляет возможность обработать ошибки:

  • Знак ? перехватывает все ошибки, которые может вернуть функция;

  • !! игнорирует ошибки, но код завершится паникой, если ошибка всё же будет.

Существует два обработчика ошибок: локальный и глобальный. Локальный всегда имеет приоритет над глобальным, т.е. все ошибки, перехваченные ?, перейдут в локальный обработчик, если он есть, иначе в глобальный.

Плагины

Netter предоставляет крейт netter_plugger, который поможет вам в создании более сложных функций, которые RDL сделать не позволит.

Пример простой функции:

use netter_plugger::{netter_plugin, generate_dispatch_func};  generate_dispatch_func!();  #[netter_plugin] fn something(     path: String, ) -> Result<String, String> {     let result = "heey".to_string();     if path == "error" {         Err("err from plugin".to_string())     } else {         Ok(format!("{result}: {path}"))     } }
  • Макрос generate_dispatch_func!(); обязательно должен находиться наверху файла. Он инициализирует входную точку в плагин

  • Атрибут #[netter_plugin] помечает функции вызываемыми из RDL

Как это работает?

Весь ваш код из функции переводится в C-совместимый код, так что готовьтесь к unsafe extern "C", хотя в базовых случаях проблем быть не должно.

После импорта вашей динамической библиотеки (которую вы ранее собрали из плагина на Rust), интерпретатор ищет и открывает её, выполняет код из либы и возвращает результат функции обратно в RDL.

Служба (демон)

Служба (или демон) помогает запускать сервера в фоне и улучшить их устойчивость.

Всё общение между клиентом (CLI) и сервисом происходит по протоколу IPC. Каждый запуск демона / службы логируется в новый файл (т.е. создаётся новый файл логов, в который записываются все логи).

Развитие проекта

Главное направление, которое я стараюсь сохранять — легкость в освоении и довольно высокая скорость разработки. Со временем проект будет постоянно развиваться в соответствии с моим виденьем и вашими запросами

Планы по развитию:

  • Графический UI на десктоп и мобильные устройства для визуализации разработки, упрощения использования инструмента и ускорения описания серверной логики;

  • Поддержка режима обратного прокси;

  • Создание балансировки нагрузок;

  • Реализация других протоколов;

  • Пакетный менеджер для плагинов (динамических библиотек).

Заключение

Это мой первый крупный проект. Не судите строго 🙂

Спасибо всем, кто прочитал «это», делится своим мнением о проекте, его проблемах, вносит вклад в его развитие!

Github


ссылка на оригинал статьи https://habr.com/ru/articles/908398/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *