CBLT — безопасный, быстрый и минималистичный веб-сервер на языке программирования Rust

от автора

Для изучения нового языка программирования я использую следующий подход. Сначала я читаю учебник по этому языку программирования, в котором объясняются синтаксис, идиомы, философия и принципы работы языка. После этого я пишу небольшой пет-проект на этом языке программирования. На пет-проекте я немного практикуюсь с новым языком, с его стандартными библиотеками и популярными фреймворками.

Чтобы погрузиться сильнее в язык, вместо пет-проекта я начинаю писать свои библиотеки для работы с базами данных (ORM), JSON, акторами, MVC веб-фреймворком, логированием и т.д. Библиотеки, которые вряд ли будут кому-то нужны, но они помогут мне лучше понять язык программирования. На удивление, с языком Rust я добрался до написания своего веб-сервера. Раньше такого не было. Думаю, это из-за того, что Rust — это язык системного программирования и грех на нём не попробовать заняться оптимизацией перформанса.

В итоге я столкнулся с тем, что Rust не имеет аналогов Nginx, Lighttpd, Caddy, HAProxy, Apache, Tomcat, Jetty и т.д. Все эти веб-сервера написаны на C, Go, Java и т.д. Имеются только веб-фреймворки: Actix, Axum, Rocket, Hyper и т.д.

В целом я прикинул, что обычно я использую Nginx для следующих целей:

1. TLS для доменов

2. Проксирование запросов на бэкэнд

3. Раздача статических файлов

В итоге решил написать свою реализацию веб-сервера на Rust.

Сервер поддерживает конфигурационный файл в формате KDL Document Language. Вот примеры «Cbltfile» конфигурационного файла для веб-сервера Cblt:

Файл сервер

"*:80" {     root "*" "/path/to/folder"     file_server }

Файл сервер & Проксирование

"127.0.0.1:8080" {     reverse_proxy "/test-api/*" "http://10.8.0.3:80"     root "*" "/path/to/folder"     file_server }

TLS поддержка

"example.com" {     root "*" "/path/to/folder"     file_server     tls "/path/to/your/domain.crt" "/path/to/your/domain.key" }

Сейчас Cblt веб-сервер можно запустить двумя способами: через Cargo или Docker.

Cargo

cargo run --release

Docker

docker build -t cblt:0.0.3 . docker run -d -p 80:80 --restart unless-stopped --name cblt cblt:0.0.3

На текущий момент я добился приемлемой скорости работы для проксирования статических файлов.

Провёл тест с Apache Benchmark (ab) для 300 запросов с 100 одновременными соединениями. Загрузка изображения размером 5 МБ с example.com/logo_huge.png.

ab -c 100 -n 300 http://example.com/logo_huge.png

Percent

Cblt

Nginx

Caddy

50%

1956

1941

1768

75%

2101

2065

1849

100%

2711

2360

2270

Cblt

igumn@lenovo MINGW64 ~/cblt (main) $ docker ps CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS                 PORTS                                                       NAMES 0589d8f26d91   cblt:0.0.1            "./cblt"                 2 minutes ago   Up 2 minutes           0.0.0.0:80->80/tcp                                          cblt  igumn@lenovo MINGW64 ~/cblt (main) $ ab -c 100 -n 300 http://example.com/logo_huge.png This is ApacheBench, Version 2.3 <$Revision: 1913912 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/  Benchmarking example.com (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Finished 300 requests   Server Software: Server Hostname:        example.com Server Port:            80  Document Path:          /logo_huge.png Document Length:        5122441 bytes  Concurrency Level:      100 Time taken for tests:   6.020 seconds Complete requests:      300 Failed requests:        0 Total transferred:      1536745500 bytes HTML transferred:       1536732300 bytes Requests per second:    49.83 [#/sec] (mean) Time per request:       2006.721 [ms] (mean) Time per request:       20.067 [ms] (mean, across all concurrent requests) Transfer rate:          249283.62 [Kbytes/sec] received  Connection Times (ms)               min  mean[+/-sd] median   max Connect:        0    0   0.3      0       2 Processing:  1293 1926 262.3   1956    2711 Waiting:        1  118 139.1     63     645 Total:       1293 1926 262.3   1956    2711  Percentage of the requests served within a certain time (ms)   50%   1956   66%   2027   75%   2101   80%   2127   90%   2213   95%   2394   98%   2544   99%   2597  100%   2711 (longest request)

Nginx

igumn@lenovo MINGW64 ~/cblt/benchmark/nginx (main) $ docker ps CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS                  PORTS                                                       NAMES 37fbf1dac42b   nginx_srv             "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes            0.0.0.0:80->80/tcp                                          nginx_srv  igumn@lenovo MINGW64 ~/cblt/benchmark/nginx (main) $ ab -c 100 -n 300 http://example.com/logo_huge.png This is ApacheBench, Version 2.3 <$Revision: 1913912 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/  Benchmarking example.com (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Finished 300 requests   Server Software:        nginx/1.27.2 Server Hostname:        example.com Server Port:            80  Document Path:          /logo_huge.png Document Length:        5122441 bytes  Concurrency Level:      100 Time taken for tests:   6.043 seconds Complete requests:      300 Failed requests:        0 Total transferred:      1536804300 bytes HTML transferred:       1536732300 bytes Requests per second:    49.65 [#/sec] (mean) Time per request:       2014.267 [ms] (mean) Time per request:       20.143 [ms] (mean, across all concurrent requests) Transfer rate:          248359.28 [Kbytes/sec] received  Connection Times (ms)               min  mean[+/-sd] median   max Connect:        0    0   0.3      0       2 Processing:  1387 1940 168.4   1941    2360 Waiting:        1  115  84.5     98     301 Total:       1387 1940 168.4   1941    2360  Percentage of the requests served within a certain time (ms)   50%   1941   66%   2024   75%   2065   80%   2088   90%   2152   95%   2201   98%   2263   99%   2317  100%   2360 (longest request)

Caddy

igumn@lenovo MINGW64 ~/cblt (main) $ ab -c 100 -n 300 http://example.com/logo_huge.png This is ApacheBench, Version 2.3 <$Revision: 1913912 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/  Benchmarking example.com (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Finished 300 requests   Server Software:        Caddy Server Hostname:        example.com Server Port:            80  Document Path:          /logo_huge.png Document Length:        5122441 bytes  Concurrency Level:      100 Time taken for tests:   5.440 seconds Complete requests:      300 Failed requests:        0 Total transferred:      1536804000 bytes HTML transferred:       1536732300 bytes Requests per second:    55.14 [#/sec] (mean) Time per request:       1813.469 [ms] (mean) Time per request:       18.135 [ms] (mean, across all concurrent requests) Transfer rate:          275858.99 [Kbytes/sec] received  Connection Times (ms)               min  mean[+/-sd] median   max Connect:        0    0   0.3      0       2 Processing:  1264 1749 191.1   1767    2270 Waiting:        1   96 104.7     67     467 Total:       1265 1749 191.1   1768    2270  Percentage of the requests served within a certain time (ms)   50%   1768   66%   1821   75%   1849   80%   1877   90%   1955   95%   2152   98%   2226   99%   2241  100%   2270 (longest request)

В планах также провести тесты для проксирования бэкенда, в общем reverse_proxy на производительность не тестировал еще.

Может в этот раз мой мини-проект кого-то заинтересует? И это увлечение вырастет в что-то большее?

Если интересно глянуть код или поконтрибутить, вот ссылка на репозиторий: https://github.com/evgenyigumnov/cblt


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


Комментарии

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

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