LINUX.ORG.RU

Cloudflare выпустила первый публичный релиз Pingora v0.1.0

 ,

Cloudflare выпустила первый публичный релиз Pingora v0.1.0

0

4

5 апреля 2024 года Cloudflare представила первый публичный релиз открытого проекта Pingora v0.1.0 (уже v0.1.1). Это асинхронный многопоточный фреймворк на Rust, который помогает создавать прокси-сервисы HTTP. Проект используется для создания сервисов, обеспечивающих значительную часть трафика в Cloudflare (вместо применения Nginx). Исходный код Pingora опубликован на GitHub под лицензией Apache 2.0.

Pingora предоставляет библиотеки и API для создания сервисов поверх HTTP/1 и HTTP/2, TLS или просто TCP/UDP. В качестве прокси-сервера он поддерживает сквозное проксирование HTTP/1 и HTTP/2, gRPC и WebSocket. Поддержка HTTP/3 — в планах. Pingora также включает в себя настраиваемые стратегии балансировки нагрузки и аварийного переключения. Чтобы соответствовать требованиям и безопасности, он поддерживает как широко используемые библиотеки OpenSSL, так и BoringSSL, которые соответствуют требованиям FIPS (федеральных стандартов обработки информации США) и пост-квантового шифрования.

Помимо этих функций, Pingora предоставляет фильтры и обратные вызовы, позволяющие пользователям полностью настраивать то, как сервис должен обрабатывать, преобразовывать и пересылать запросы.

В рабочем режиме Pingora обеспечивает плавный перезапуск без простоев для самостоятельного обновления, не теряя ни одного входящего запроса. Syslog, Prometheus, Sentry, OpenTelemetry и другие необходимые инструменты наблюдения легко интегрируются с Pingora.

Возможности Pingora: использование Async Rust, поддержка HTTP 1/2 end to end proxy, TLS over OpenSSL или BoringSSL, gRPC и проксирование веб-сокетов, Graceful reload, настраиваемые стратегии балансировки нагрузки и аварийного переключения, поддержка различных инструментов мониторинга.

В версии Pingora v0.1.1 исправлены ранее обнаруженные ошибки, улучшена производительность алгоритма pingora-ketama, добавлено больше бенчмарков TinyUFO и тестов для pingora-cache purge, ограничен размер буфера для журналов ошибок InvalidHTTPHeader, а также исправлены опечатки и внесены необходимые исправления в комментариях и документации проекта.

>>> Подробности

★★★

Проверено: hobbit ()
Последнее исправление: hobbit (всего исправлений: 1)

Ответ на: комментарий от monk

Умный компилятор может сделать вывод, что name = buf никогда не может быть, значит symbol->m_name всегда истинно.

Да ладно, я спокойно могу в си опустить 2й параметр, вызвать просто dump_hsa_symbol (f).

А вообще не понял, где тут косяк то ?

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Я же писал есть кодер а есть программист.

Любопытно, а как вы себя позиционируете? С такими скиллами чтения кода, скорее, новичок? Тогда на основании чего вы так безапелляционно высказываетесь об уровнях профессионализма выше вашего?

unC0Rr ★★★★★
()
Ответ на: комментарий от mx__

Так про то и речь, что когда в Си++ UB, может вызваться что угодно, даже если по коду программы вызываться никогда не должно.

monk ★★★★★
()
Ответ на: комментарий от unC0Rr

Да я наверное уже 20 как перестал программировать. Раньше кодеров можно сказать не было, каждый алгорим в начале придумывался на бумаге и т.д.

Но я уважаю людей кто мне технически возражает и приводит примеры реальные, и я вроде никого еще не обвинил что ОН конкретно (если так сделал приведите пожалуйста ссылку) что его уровень ниже моего и т.д. А вот обратку уже много раз видел даже в этой ветке.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Да ладно, я спокойно могу в си опустить 2й параметр, вызвать просто dump_hsa_symbol (f).

???

<source>:11:5: error: too few arguments to function 'dump_hsa_symbol'
   11 |     dump_hsa_symbol(f);

А вообще не понял, где тут косяк то ?

name = buf запоминает адрес локальных данных в блоке, который на следующей строке прекращает существование. Следующее чтение этого адреса будет UB. Компилятор отсюда может сделать вывод, что эта ветка не может выполняться и выкинуть проверку в if и оставить только первую ветку. А также запомнить, что проверка в if всегда истинна (иначе было бы UB).

monk ★★★★★
()
Ответ на: комментарий от monk

Извините но если честно не понял ВАС, в приведенном примере явный вызов, т.е. обычный человеческий фактор, ну это нормально.

mx__ ★★★★★
()
Ответ на: комментарий от monk

Так стоп, почему то мне помнилось что можно, я буду это проверять и только потом напишу.

mx__ ★★★★★
()
Ответ на: комментарий от monk

Если бы Java и С++ могли вызывать методы друг друга

Объясните, бога ради, какое отношение имеет стековая виртуальная машина со сборщиком мусора, к тому как раст решает проблему безопасного управления памятью на этапе компиляции. Как одно может заменить другое, если это совсем про разное?

FishHook
()
Ответ на: комментарий от FishHook

Проблема управления памятью не решается на этапе компиляции, это невозможно, и это не зависит от языка.

Как пример, у тебя есть текстуры, в игре, если противник вышел за пределы видимости, текстуру нужно освободить.

Когда то произойдет, тебе известно только в момент выполнения.

Это можно неэффективно решить через стандартные умные указатели раста, например через Rc<>, в Java это решает более быстрый и продвинутый сборщик мусора.

В Java есть JIT, поэтому это не просто виртуальная стековая машина.

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от MOPKOBKA

Это можно неэффективно решить через стандартные умные указатели раста, например через Rc<>, в Java это решает более быстрый и продвинутый сборщик мусора.

Эммм, что? Одна операция икремента - это неэффективно? А сборщик мусора обходится без счетчика ссылок? Что вы несете???

FishHook
()
Ответ на: комментарий от mx__

в приведенном примере явный вызов

Явного вызова NeverCalled нет. Но Си++ его вызывает потому что UB (а значит всё можно).

monk ★★★★★
()
Ответ на: комментарий от FishHook

Оба варианта решают проблему с UB.

monk ★★★★★
()
Ответ на: комментарий от FishHook

Эммм, что? Одна операция икремента - это неэффективно?

Крайне, ведь эти операции происходят всегда, например ты хочешь получить текстуру, но на самом деле ты не просто прочтешь структуру, но и сделаешь запись (передача Rc вызовет inc а потом dec). Счетчик еще часто бывает атомарным, если нужно больше 1 потока, а это еще сильнее замедляет.

А сборщик мусора обходится без счетчика ссылок?

Да, конечно, чистый счетчик ссылок используют только наименее продвинутые сборщики мусора (так не делают Java, C#, и другие), даже самый первый сборщик мусора в истории так не делал.

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 4)
Ответ на: комментарий от monk

Тьфу :( Полез по ссылки почитал, To fix this error, we should declare the buf array in the same scope as the name pointer :(

Ну так это ошибка в коде, блин зачем мы это разбираем ?

mx__ ★★★★★
()
Ответ на: комментарий от mx__

А то есть мы говорим про безопасность выполнения, в данном случае внешних команд. Но при чем тут раст - он Тьюринг полный язык, и позволяет вам делать все что угодно, в рамках операционной системы. Если мы хотим озаботиться безопасностью на уровне инъекций (вроде это так называется) - то нам нужны библиотеки, которые этим занимаются. Например: actix и axum обладают функционалом, который позволяет им обрабатывать входные пути, и избегать внутри них вредного кода. diesel и sqlx - обладают функционалом проверки sql запросов. Если подобное надо написать для оболочки типа bash/sh/zsh и тп. - то это вполне возможно выполнить в роли crate или trait.

Silerus ★★★★
()
Ответ на: комментарий от mx__

Вы там UB пытаетесь найти? Мне лень читать всю ветку, но возможно этот пример заинтересует:

#include <stdio.h>

void f(int* a, short* b) {
  *a = 0;
  *b = 1;
  printf("%d,%d\n", (int)*a, (int)*b); // Выводит 0, 1
}

int main() {
    int i = -1;
    f(&i, (short*)&i);
}

MOPKOBKA ★★★★
()
Ответ на: комментарий от mx__

Так любой UB является ошибкой в коде. Но если язык без UB, то ошибка кода будет локальной (в этой точке может что-то не так посчитаться, может произойти исключение, …). А в языке с UB может перестать работать в совсем другом месте или выполниться произвольный кусок кода.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от MOPKOBKA

Как пример, у тебя есть текстуры, в игре, если противник вышел за пределы видимости, текстуру нужно освободить. Когда то произойдет, тебе известно только в момент выполнения.

Стоп не очень понял. Что значит выйдет за пределы видимости ? В проге при перемещении противника рассчитывается текущее его расстояние до тебя, и как только оно выше видимости то …

mx__ ★★★★★
()
Ответ на: комментарий от monk

НО если язык без UB,

Что значит язык без UB ? Не понимаю, вон я кинул пример на Rust оно что не выполнит rm ?

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Что значит язык без UB ? Не понимаю, вон я кинул пример на Rust оно что не выполнит rm ?

UB = Undefined behaviour = неопределённое поведение, прописанной в описании языка. То есть, когда язык на определённые последовательности кода может делать что угодно. Вызывать код, который ниоткуда не вызывается, менять данные, выбрасывать куски кода. Причём кусок кода может даже не выполняться:

int *p;
if (check_password(login, password)) {
  grant_access();
} else {
  log(login);
  *p = *p + 1;
}

преобразуется компилятором в безусловный

grant_access();

Потому что во второй ветке есть UB.

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

monk ★★★★★
()
Ответ на: комментарий от mx__

Это не UB, UB - это не предвиденное поведения, которое зависит от версии компилятора, состояния меркурия и т.п. Например чтение из удаленой/освобожденной области памяти - это может быть ub, потому что там может быть как старые данные, так и данные, которые там оказались, в результате создания новой переменной.

Silerus ★★★★
()
Ответ на: комментарий от Qui-Gon

Аплодирую.

Правда, мне кажется, мозила сама поняла, что эксперимент не очень удачный. Поддержка проекта на двух (прикладных, не скриптовых) языках всегда сложнее, чем поддержка проекта на одном языке. (Речь про firefox) Это усугубляется еще и тем, что парадигмы у языков разные.

zx_gamer ★★
()
Ответ на: комментарий от Silerus

Это не UB, UB - это не предвиденное поведения, которое зависит от версии компилятора, состояния меркурия и т.п.

По стандарту Си/Си++ и схожих языков (Zig, …) именно это UB.

А зависимость от компилятора и прочего — это определяемое реализацией = implementation defined = IB.

Например чтение из удаленой/освобожденной области памяти - это может быть ub, потому что там может быть как старые данные, так и данные, которые там оказались, в результате создания новой переменной.

Если в стандарте написано, что чтение из удаленой/освобожденной области памяти может вернуть произвольные данные, тогда это IB. Если же в стандарте написано, что это UB, тогда это чтение может вообще не возвращать данные, а например, отформатировать диск. Или изменить код программы произвольным образом. И компилятор вправе постулировать, что UB никогда не случается, то есть, если написано if(x < 0){ здесь UB }, значит x всегда неотрицательно.

P.S. Не на то ответил… Хотел ответить mx

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от Silerus

Не считаю си UB так как ядро работает у всех.

Кстати вот UB можно считать PERL так как там математически доказали что видя код проги и не выполнив ее НИКОГДА нелья узнать результат выполнения ;)

mx__ ★★★★★
()
Ответ на: комментарий от monk

Мы говорим о том что выполняется команда rm, а по мнению mx__ - не должна, так как это вредит системе - это не ub. Программа выполняет что ей сказано, если надо проверять внешний код на опасность - это отдельная песня

Silerus ★★★★
()
Ответ на: комментарий от monk

Исходя из этого определения то результат выполнение программы должен быть всегда разный, но увы это не так.

Извините меня, но это все почему то смахивает на маркетинговый бред, я могу это понять в аналоговом мире в цифровом у меня это не получается.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Не считаю си UB так как ядро работает у всех.

Так в его коде и нет UB, потому и работает. UB свойство языка, а не программы. Для Си существуют куски кода, которые могут делать что угодно.

Для PERL, кстати, таких кусков нет. Синтаксический разбор конца программы может зависеть от выполнения её начала, но семантика каждой команды однозначная.

monk ★★★★★
()
Ответ на: комментарий от mx__

В си есть такое понятие как ub - оно есть в документации, патерны, которые приводят к таким ситуация, стоит избегать. Некоторые программисты намерено используют ub, например для достижения быстродействия. Код с ub - становится платформо/компиляторо-зависимым

Silerus ★★★★
()
Последнее исправление: Silerus (всего исправлений: 1)
Ответ на: комментарий от mx__

Что значит выйдет за пределы видимости?

Distance > VIEW_DISTANCE_MAX

В проге при перемещении противника рассчитывается текущее его расстояние до тебя, и как только оно выше видимости то …

Это ты алгоритм предложил? Он так себе, текстуру ведь может в это время использовать другой противник, и трупы.

MOPKOBKA ★★★★
()
Ответ на: комментарий от No

RAII хорошо работает только в простых случаях.

Везде он нормально работает.

Если, например, где-то сохраняется указатель на объект, то можно легко получить use after free:

Очевидно. Но зачем так делать? Можно написать код, который что-то делит на 0. Но вопрос тот же — зачем так делать?

Если человек программист, а не чайник, то ему даже в голову не придёт сохранять указатель на объект, который уничтожится после выхода их скоупа.

zx_gamer ★★
()
Ответ на: комментарий от mx__

Исходя из этого определения то результат выполнение программы должен быть всегда разный, но увы это не так.

Ну вот пример:

int main()
{
   char s[100];
   s[99] = 0;
   printf("%s", s);
   return 0;
}

Результат будет всегда разный.

monk ★★★★★
()
Ответ на: комментарий от zx_gamer

Если человек программист, а не чайник, то ему даже в голову не придёт сохранять указатель на объект, который уничтожится после выхода их скоупа.

Разработчики компилятора gcc чайники? Вот же именно это: Cloudflare выпустила первый публичный релиз Pingora v0.1.0 (комментарий)

monk ★★★★★
()
Ответ на: комментарий от monk

А на что тут ругаться? Это корректный код.

А если ему будет передана строка менее, чем из 6 символов, то, да санитайзеры gcc и valgrind покажут ошибку и stack trace.

zx_gamer ★★
()
Ответ на: комментарий от MOPKOBKA

Крайне, ведь эти операции происходят всегда

В смысле всегда? Они происходят, когда ты вызываешь RC::clone(), зачем тебе это делать на статических данных?

FishHook
()
Ответ на: комментарий от zx_gamer

А если ему будет передана строка менее, чем из 6 символов, то, да санитайзеры gcc и valgrind покажут ошибку и stack trace.

Да?

extern void f(char *s, char c);

void g()
{
   char s[3] = "ok";
   f(s, 5);
}

На этот код кто из них ругнётся? И на основании чего?

monk ★★★★★
()
Ответ на: комментарий от monk

И что ?

Стоп, вы хотите сказать что аналогичная прога на расте даст всегда одинаковый результат ?

Насколько я помню в go (ну это можно проверить) тоже даст разный результат.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Исходя из этого определения то результат выполнение программы должен быть всегда разный

Нет такого в определении.

unC0Rr ★★★★★
()
Ответ на: комментарий от MOPKOBKA

Это корректный код на Си. Не стоит путать нормальный C89 с C99 в котором есть strict aliasing rule.

Этот код выводит «1,1». Либо укажите, что хотите использовать ANSI C (флаг -ansi для GCC), либо выключите strict aliasing (флаг -fno-strict-aliasing для GCC).

zx_gamer ★★
()
Ответ на: комментарий от FishHook

Я про это и говорю, передаешь ты структуру куда то, на обработку дополнительную, и получи запись, враг умирает, запись, враг создается запись. Это может быть не враг а предмет, количество предметов в современных играх довольно приличное, текстур на одном предмете несколько.

Предметы двигаются, npc ходят, машины ездют туда сюда, каждый кадр у тебя инкременты декременты, возможно даже на атомиках.

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от monk

К компилятору претензий нет. Он транслирует то, что ему подали на вход как есть. Прикладное ПО могут писать чайники, которые не знают, что так делать нельзя.

zx_gamer ★★
()
Ответ на: комментарий от zx_gamer

Это код с UB, используя такой наткнешься на проблемы, придется включать -fno костыли и молиться. Вот в соседней теме модуль ядра не собирается с -O0.

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от monk

Во-первых extern перед функцией ничего не значит. Он имеет смысл только перед глобальной переменной.

Во-вторых при сборке проекта с санитайзером в функцию f будет вставлена проверка выхода за границу.

zx_gamer ★★
()
Ответ на: комментарий от monk

На этот код кто из них ругнётся? И на основании чего?

На основании выхода за пределы массива, правда произойдет это только в runtime для твоего примера, но есть инструменты что бы такого не происходило:

void f(int n, char s[static n]);

int main() {
        char s[] = "ok";
        f(5, s);
}

main.c:5:9: warning: ‘f’ accessing 5 bytes in a region of size 3 [-Wstringop-overflow=]
    5 |         f(5, s);
      |         ^~~~~~~

MOPKOBKA ★★★★
()
Ответ на: комментарий от zx_gamer

Да, однако это очень плохой код, если ему нужны подпорки для работы. Еще и использующий якори, которые не дают перейти на более актуальный стандарт и использовать его преимущества.

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от monk

У меня этот код ничего не выдает вообще.

mx__ ★★★★★
()
Ответ на: комментарий от MOPKOBKA

В новых «стандартах» языка Си смысла просто нет. Они не дают новых возможностей, зато ломают старый код.

Очень много программистов кладут с прибором на C после C89 и ИМХО правильно делают.

zx_gamer ★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.