diff --git a/frameworks/userver/meta.json b/frameworks/userver/meta.json index 94e53d06d..4adccd925 100644 --- a/frameworks/userver/meta.json +++ b/frameworks/userver/meta.json @@ -1,14 +1,15 @@ { "display_name": "userver", "language": "C++", - "type": "tuned", + "type": "production", "engine": "userver", "description": "Asynchronous framework with a rich set of abstractions for fast and comfortable creation of C++ microservices, services and utilities", "repo": "https://github.com/userver-framework/userver", "enabled": true, "tests": [ "baseline", - "pipelined" + "pipelined", + "static" ], "maintainers": [] } diff --git a/frameworks/userver/userver_benchmark/CMakeLists.txt b/frameworks/userver/userver_benchmark/CMakeLists.txt index 93ce73ace..1e9ff8b44 100644 --- a/frameworks/userver/userver_benchmark/CMakeLists.txt +++ b/frameworks/userver/userver_benchmark/CMakeLists.txt @@ -6,7 +6,6 @@ set(CMAKE_CXX_STANDARD 20) file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/controllers/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/common/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/bare/*.cpp ) include(GNUInstallDirs) diff --git a/frameworks/userver/userver_benchmark/bare/simple_connection.cpp b/frameworks/userver/userver_benchmark/bare/simple_connection.cpp deleted file mode 100644 index c2ffe15e6..000000000 --- a/frameworks/userver/userver_benchmark/bare/simple_connection.cpp +++ /dev/null @@ -1,202 +0,0 @@ -#include "simple_connection.hpp" - -#include - -#include -#include -#include - -#include "simple_server.hpp" - -#include -#include -#include -#include - -namespace userver_httparena::bare { - -namespace { - -struct HttpParser final { - llhttp_t parser{}; - llhttp_settings_t parser_settings{}; - - std::function on_request_cb{}; - - userver::utils::SmallString<50> url; - - explicit HttpParser(std::function on_request_cb) - : on_request_cb{std::move(on_request_cb)} { - llhttp_settings_init(&parser_settings); - parser_settings.on_url = HttpOnUrl; - parser_settings.on_message_begin = HttpOnMessageBegin; - parser_settings.on_message_complete = HttpOnMessageComplete; - - llhttp_init(&parser, HTTP_REQUEST, &parser_settings); - parser.data = this; - } - - auto Execute(const char* data, std::size_t length) { - return llhttp_execute(&parser, data, length); - } - - static int HttpOnUrl(llhttp_t* parser, const char* data, std::size_t length) { - auto* self = static_cast(parser->data); - self->url.append(std::string_view{data, length}); - return 0; - } - - static int HttpOnMessageBegin(llhttp_t* parser) { - auto* self = static_cast(parser->data); - self->url.clear(); - return 0; - } - - static int HttpOnMessageComplete(llhttp_t* parser) { - auto* self = static_cast(parser->data); - self->on_request_cb(static_cast(self->url)); - return 0; - } -}; - -class ResponseBuffers final { - public: - using HeadersString = userver::utils::SmallString<200>; - - HeadersString& Next(userver::engine::io::Socket& socket, std::string&& body) { - if (Size() == kMaxResponses) { - Send(socket); - } - - auto& response = responses_.emplace_back(); - response.body = std::move(body); - return response.headers; - } - - void Send(userver::engine::io::Socket& socket) { - if (Size() == 0) { - return; - } - - boost::container::small_vector io_vector( - Size() * 2); - - std::size_t index = 0; - std::size_t total_size = 0; - for (auto& response : responses_) { - io_vector[index++] = {response.headers.data(), response.headers.size()}; - io_vector[index++] = {response.body.data(), response.body.size()}; - total_size += response.headers.size() + response.body.size(); - } - - if (socket.SendAll(io_vector.data(), io_vector.size(), {}) != total_size) { - throw std::runtime_error{"Socket closed by remote"}; - } - - responses_.clear(); - } - - private: - static constexpr std::size_t kMaxResponses = 16; - - [[nodiscard]] std::size_t Size() const { return responses_.size(); } - - struct Response final { - HeadersString headers; - std::string body; - }; - - boost::container::small_vector responses_; -}; - -constexpr std::string_view kCommonHeaders{"HTTP/1.1 200 OK\r\nServer: userver\r\n"}; -constexpr std::string_view kHeadersEnd{"\r\n\r\n"}; - -std::string MakeHttpDate(std::chrono::system_clock::time_point date) { - static const std::string kFormatString = "%a, %d %b %Y %H:%M:%S %Z"; - static const auto tz = cctz::utc_time_zone(); - - return cctz::format(kFormatString, date, tz); -} - -std::string_view GetCachedDate() { - constexpr size_t kMaxDateHeaderLength = 128; - - static thread_local std::chrono::seconds::rep last_second = 0; - static thread_local char last_time_string[kMaxDateHeaderLength]{}; - static thread_local std::string_view result_view{}; - - const auto now = userver::utils::datetime::WallCoarseClock::now(); - const auto now_seconds = - std::chrono::duration_cast(now.time_since_epoch()) - .count(); - if (now_seconds != last_second) { - last_second = now_seconds; - - const auto time_str = MakeHttpDate(now); - - std::memcpy(last_time_string, time_str.c_str(), time_str.size()); - result_view = std::string_view{last_time_string, time_str.size()}; - } - - return result_view; -} - -} // namespace - -SimpleConnection::SimpleConnection(SimpleServer& server, - userver::engine::io::Socket&& socket) - : server_{server}, - socket_{std::move(socket)}, - processing_task_{userver::engine::AsyncNoSpan([this] { Process(); })} {} - -SimpleConnection::~SimpleConnection() { processing_task_.SyncCancel(); } - -void SimpleConnection::Process() { - constexpr std::size_t kBufferSize = 4096; - std::array buffer{}; - - userver::utils::ScopeGuard close_guard{[this] { socket_.Close(); }}; - - ResponseBuffers buffers{}; - const auto handle_request = [this, &buffers](std::string_view url) { - auto response = server_.HandleRequest(url); - const auto content_length_str = std::to_string(response.body.size()); - auto& headers = buffers.Next(socket_, std::move(response.body)); - - headers.append(kCommonHeaders); - headers.append("Content-Type: "); - headers.append(response.content_type); - - headers.append("\r\nContent-Length: "); - headers.append(content_length_str); - - headers.append("\r\nDate: "); - headers.append(GetCachedDate()); - - headers.append(kHeadersEnd); - }; - HttpParser parser{handle_request}; - - std::size_t last_bytes_read = 0; - while (true) { - bool is_readable = true; - if (last_bytes_read < kBufferSize) { - is_readable = socket_.WaitReadable({}); - } - - last_bytes_read = - is_readable ? socket_.RecvSome(buffer.data(), kBufferSize, {}) : 0; - if (last_bytes_read == 0) { - break; - } - - if (parser.Execute(buffer.data(), last_bytes_read) != HPE_OK) { - break; - } - - buffers.Send(socket_); - } -} - -} // namespace userver_httparena::bare diff --git a/frameworks/userver/userver_benchmark/bare/simple_connection.hpp b/frameworks/userver/userver_benchmark/bare/simple_connection.hpp deleted file mode 100644 index 50065f5f4..000000000 --- a/frameworks/userver/userver_benchmark/bare/simple_connection.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include -#include - -namespace userver_httparena::bare { - -class SimpleServer; - -class SimpleConnection final { - public: - explicit SimpleConnection(SimpleServer& server, - userver::engine::io::Socket&& socket); - ~SimpleConnection(); - - private: - void Process(); - - const SimpleServer& server_; - - userver::engine::io::Socket socket_; - - userver::engine::TaskWithResult processing_task_; -}; - -} // namespace userver_httparena::bare diff --git a/frameworks/userver/userver_benchmark/bare/simple_response.hpp b/frameworks/userver/userver_benchmark/bare/simple_response.hpp deleted file mode 100644 index 852f35ace..000000000 --- a/frameworks/userver/userver_benchmark/bare/simple_response.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include - -namespace userver_httparena::bare { - -struct SimpleResponse final { - std::string body; - std::string content_type; -}; - -} // namespace userver_httparena::bare diff --git a/frameworks/userver/userver_benchmark/bare/simple_router.cpp b/frameworks/userver/userver_benchmark/bare/simple_router.cpp deleted file mode 100644 index 6a46e5687..000000000 --- a/frameworks/userver/userver_benchmark/bare/simple_router.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "simple_router.hpp" - -#include - -#include "../controllers/plaintext/handler.hpp" -#include "../controllers/baseline11/handler.hpp" -#include "../controllers/json/handler.hpp" -#include "../controllers/single_query/handler.hpp" - -namespace userver_httparena::bare { - -namespace { - -constexpr std::string_view kPlainTextUrlPrefix{"/pipeline"}; -constexpr std::string_view kBaseLine11UrlPrefix{"/baseline11"}; -constexpr std::string_view kJsonUrlPrefix{"/json"}; -constexpr std::string_view kSingleQueryUrlPrefix{"/async-db"}; - -// NOLINTNEXTLINE -const std::string kContentTypePlain{"text/plain"}; -// NOLINTNEXTLINE -const std::string kContentTypeJson{"application/json"}; -// NOLINTNEXTLINE -const std::string kContentTypeTextHtml{"text/html; charset=utf-8"}; - -bool StartsWith(std::string_view source, std::string_view pattern) -{ - return source.substr(0, pattern.length()) == pattern; -} - -} // namespace - -SimpleRouter::SimpleRouter(const userver::components::ComponentConfig& config, - const userver::components::ComponentContext& context) - : userver::components::LoggableComponentBase{config, context}, - single_query_{context.FindComponent()} { } - -SimpleRouter::~SimpleRouter() = default; - -SimpleResponse SimpleRouter::RouteRequest(std::string_view url) const -{ - if (StartsWith(url, kPlainTextUrlPrefix)) { - return {plaintext::Handler::GetResponse(), kContentTypePlain}; - } - - if (StartsWith(url, kBaseLine11UrlPrefix)) { - return {baseline11::Handler::GetResponse("1000", "2000", "3000"), kContentTypePlain}; - } - - if (StartsWith(url, kJsonUrlPrefix)) { - return {json::Handler::GetResponse(), kContentTypeJson}; - } - - if (StartsWith(url, kSingleQueryUrlPrefix)) { - return {single_query_.GetResponse(), kContentTypeJson}; - } - - throw std::runtime_error{"No handler found for url"}; -} - -} // namespace userver_httparena::bare diff --git a/frameworks/userver/userver_benchmark/bare/simple_router.hpp b/frameworks/userver/userver_benchmark/bare/simple_router.hpp deleted file mode 100644 index f4366bd68..000000000 --- a/frameworks/userver/userver_benchmark/bare/simple_router.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include - -#include "simple_response.hpp" - -namespace userver_httparena { - -namespace single_query { -class Handler; -} - -namespace bare { - -class SimpleRouter final : public userver::components::LoggableComponentBase { - public: - static constexpr std::string_view kName{"simple-router"}; - - SimpleRouter(const userver::components::ComponentConfig& config, - const userver::components::ComponentContext& context); - ~SimpleRouter() final; - - [[nodiscard]] SimpleResponse RouteRequest(std::string_view url) const; - - private: - const single_query::Handler& single_query_; -}; - -} // namespace bare -} // namespace userver_httparena diff --git a/frameworks/userver/userver_benchmark/bare/simple_server.cpp b/frameworks/userver/userver_benchmark/bare/simple_server.cpp deleted file mode 100644 index c4549a87f..000000000 --- a/frameworks/userver/userver_benchmark/bare/simple_server.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "simple_server.hpp" - -#include -#include - -#include "simple_connection.hpp" -#include "simple_router.hpp" - -namespace userver_httparena::bare { - -SimpleServer::SimpleServer(const userver::components::ComponentConfig& config, - const userver::components::ComponentContext& context) - : userver::components::TcpAcceptorBase(config, context), - router_{context.FindComponent()} {} - -SimpleServer::~SimpleServer() = default; - -void SimpleServer::ProcessSocket(userver::engine::io::Socket&& socket) { - const auto fd = socket.Fd(); - connections_[fd] = - std::make_unique(*this, std::move(socket)); -} - -SimpleResponse SimpleServer::HandleRequest(std::string_view url) const { - return router_.RouteRequest(url); -} - -} // namespace userver_httparena::bare diff --git a/frameworks/userver/userver_benchmark/bare/simple_server.hpp b/frameworks/userver/userver_benchmark/bare/simple_server.hpp deleted file mode 100644 index 46ad87cca..000000000 --- a/frameworks/userver/userver_benchmark/bare/simple_server.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include "simple_response.hpp" - -namespace userver_httparena::bare { - -class SimpleConnection; -class SimpleRouter; - -class SimpleServer final : public userver::components::TcpAcceptorBase { - public: - static constexpr std::string_view kName{"simple-server"}; - - SimpleServer(const userver::components::ComponentConfig& config, - const userver::components::ComponentContext& context); - ~SimpleServer() final; - - private: - void ProcessSocket(userver::engine::io::Socket&& socket) final; - - friend class SimpleConnection; - [[nodiscard]] SimpleResponse HandleRequest(std::string_view url) const; - - const SimpleRouter& router_; - - static constexpr std::size_t kMaxFd = 65536; - std::array, kMaxFd> connections_; -}; -} // namespace userver_httparena::bare diff --git a/frameworks/userver/userver_benchmark/userver_httparena.cpp b/frameworks/userver/userver_benchmark/userver_httparena.cpp index 41ddba662..fc016e956 100644 --- a/frameworks/userver/userver_benchmark/userver_httparena.cpp +++ b/frameworks/userver/userver_benchmark/userver_httparena.cpp @@ -4,7 +4,9 @@ #include +#include #include +#include #include #include #include @@ -15,9 +17,6 @@ #include "controllers/json/handler.hpp" #include "controllers/single_query/handler.hpp" -#include "bare/simple_router.hpp" -#include "bare/simple_server.hpp" - namespace userver_httparena { class NoopTracingManager final @@ -52,6 +51,8 @@ int Main(int argc, char* argv[]) .Append() .Append() .Append() + .Append("fs-cache-static") + .Append() .Append("hello-world-db") // actual handlers .Append() @@ -60,9 +61,6 @@ int Main(int argc, char* argv[]) .Append() // tracing tweaks .Append() - // bare (not used in the benchmark currently) - .Append() - .Append() ; return userver::utils::DaemonMain(argc, argv, component_list); } diff --git a/frameworks/userver/userver_configs/static_config.yaml b/frameworks/userver/userver_configs/static_config.yaml index 5fe1e2598..95a5bca6f 100644 --- a/frameworks/userver/userver_configs/static_config.yaml +++ b/frameworks/userver/userver_configs/static_config.yaml @@ -28,10 +28,6 @@ components_manager: #handler-defaults: # set_tracing_headers: false server-name: userver - simple-router: - simple-server: - port: 8081 - task_processor: main-task-processor logging: fs-task-processor: fs-task-processor loggers: @@ -44,8 +40,8 @@ components_manager: fs-task-processor: fs-task-processor dynamic-config: # Dynamic config storage options, do nothing + updates-enabled: false fs-cache-path: '' - defaults-path: /app/dynamic_config_fallback.json fs-task-processor: fs-task-processor testsuite-support: @@ -59,6 +55,17 @@ components_manager: tracing-manager-locator: component-name: noop-tracing-manager + fs-cache-static: + dir: /data/static/ + update-period: 60s + fs-task-processor: fs-task-processor + + handler-static: + fs-cache-component: fs-cache-static + path: /static/* + method: GET + task_processor: main-task-processor + plaintext-handler: path: /pipeline method: GET @@ -88,7 +95,7 @@ components_manager: connlimit_mode: manual single-query-handler: - path: /async-db + path: /single-query method: GET decompress_request: false task_processor: main-task-processor