Skip to content

Drogon — 高性能 Web 框架

Drogon 是 C++ 最快的 Web 框架之一,基于 Boost.Asio,支持 HTTP/WebSocket/协程,TechEmpower 基准测试中名列前茅。

安装

bash
# Ubuntu
sudo apt install libjsoncpp-dev libssl-dev uuid-dev zlib1g-dev
git clone https://github.com/drogonframework/drogon
cd drogon && git submodule update --init
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build && sudo cmake --install build

# vcpkg
vcpkg install drogon

# CMake
find_package(Drogon REQUIRED)
target_link_libraries(myapp PRIVATE Drogon::Drogon)

快速开始

cpp
#include <drogon/drogon.h>

int main() {
    // 注册路由
    drogon::app()
        .addListener("0.0.0.0", 8080)
        .setThreadNum(4);

    // 简单路由
    drogon::app().registerHandler("/",
        [](const drogon::HttpRequestPtr& req,
           std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
            auto resp = drogon::HttpResponse::newHttpResponse();
            resp->setBody("Hello, Drogon!");
            callback(resp);
        });

    // JSON 响应
    drogon::app().registerHandler("/api/hello",
        [](const drogon::HttpRequestPtr& req, auto&& callback) {
            Json::Value json;
            json["message"] = "Hello, World!";
            json["version"] = "1.0";
            auto resp = drogon::HttpResponse::newHttpJsonResponse(json);
            callback(resp);
        });

    drogon::app().run();
}

控制器(Controller)

cpp
#include <drogon/HttpController.h>

// HTTP 控制器
class UserController : public drogon::HttpController<UserController> {
public:
    METHOD_LIST_BEGIN
        ADD_METHOD_TO(UserController::getUser,  "/api/users/{id}", drogon::Get);
        ADD_METHOD_TO(UserController::createUser, "/api/users",    drogon::Post);
        ADD_METHOD_TO(UserController::listUsers,  "/api/users",    drogon::Get);
    METHOD_LIST_END

    // GET /api/users/{id}
    void getUser(const drogon::HttpRequestPtr& req,
                 std::function<void(const drogon::HttpResponsePtr&)>&& callback,
                 int id) {
        Json::Value json;
        json["id"] = id;
        json["name"] = "Alice";
        callback(drogon::HttpResponse::newHttpJsonResponse(json));
    }

    // POST /api/users
    void createUser(const drogon::HttpRequestPtr& req,
                    std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
        auto body = req->getJsonObject();
        if (!body) {
            auto resp = drogon::HttpResponse::newHttpResponse();
            resp->setStatusCode(drogon::k400BadRequest);
            resp->setBody("Invalid JSON");
            callback(resp);
            return;
        }

        std::string name = (*body)["name"].asString();
        Json::Value result;
        result["id"] = 1;
        result["name"] = name;
        result["created"] = true;

        auto resp = drogon::HttpResponse::newHttpJsonResponse(result);
        resp->setStatusCode(drogon::k201Created);
        callback(resp);
    }

    void listUsers(const drogon::HttpRequestPtr& req,
                   std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
        // 查询参数
        auto page = req->getParameter("page");
        auto limit = req->getParameter("limit");

        Json::Value users(Json::arrayValue);
        // ... 查询数据库
        callback(drogon::HttpResponse::newHttpJsonResponse(users));
    }
};

协程控制器(推荐)

cpp
#include <drogon/HttpCoroController.h>

class ApiController : public drogon::HttpCoroController<ApiController> {
public:
    METHOD_LIST_BEGIN
        ADD_METHOD_TO(ApiController::getUser, "/api/users/{id}", drogon::Get);
    METHOD_LIST_END

    // 协程风格,代码更清晰
    drogon::Task<> getUser(drogon::HttpRequestPtr req,
                           std::function<void(const drogon::HttpResponsePtr&)> callback,
                           int id) {
        // co_await 异步数据库查询
        auto result = co_await drogon::orm::CoroMapper<User>(drogon::app().getDbClient())
            .findByPrimaryKey(id);

        Json::Value json;
        json["id"] = result.getValueOfId();
        json["name"] = result.getValueOfName();
        callback(drogon::HttpResponse::newHttpJsonResponse(json));
    }
};

中间件与过滤器

cpp
#include <drogon/HttpFilter.h>

// 认证过滤器
class AuthFilter : public drogon::HttpFilter<AuthFilter> {
public:
    void doFilter(const drogon::HttpRequestPtr& req,
                  drogon::FilterCallback&& fcb,
                  drogon::FilterChainCallback&& fccb) override {
        auto token = req->getHeader("Authorization");
        if (token.empty() || !verify_token(token)) {
            auto resp = drogon::HttpResponse::newHttpResponse();
            resp->setStatusCode(drogon::k401Unauthorized);
            Json::Value json;
            json["error"] = "Unauthorized";
            resp->setBody(json.toStyledString());
            fcb(resp);  // 拦截请求
            return;
        }
        fccb();  // 放行
    }
};

// 在控制器上应用过滤器
class ProtectedController : public drogon::HttpController<ProtectedController> {
public:
    METHOD_LIST_BEGIN
        ADD_METHOD_TO(ProtectedController::secret,
                      "/api/secret", drogon::Get,
                      "AuthFilter");  // 应用过滤器
    METHOD_LIST_END

    void secret(const drogon::HttpRequestPtr& req, auto&& callback) {
        // 只有通过认证才能到达这里
        callback(drogon::HttpResponse::newHttpResponse());
    }
};

数据库集成

cpp
#include <drogon/orm/DbClient.h>

// 配置数据库(config.json)
// {
//   "db_clients": [{
//     "name": "default",
//     "rdbms": "postgresql",
//     "host": "localhost",
//     "port": 5432,
//     "dbname": "mydb",
//     "user": "postgres",
//     "passwd": "password",
//     "connection_number": 10
//   }]
// }

// 协程数据库查询
drogon::Task<> queryUsers() {
    auto db = drogon::app().getDbClient();

    // 原始 SQL
    auto result = co_await db->execSqlCoro(
        "SELECT id, name FROM users WHERE age > $1", 18);

    for (auto& row : result) {
        std::cout << row["id"].as<int>() << ": "
                  << row["name"].as<std::string>() << "\n";
    }

    // ORM(需要 drogon_ctl 生成模型)
    auto users = co_await drogon::orm::CoroMapper<User>(db)
        .orderBy(User::Cols::_age)
        .limit(10)
        .findAll();
}

配置文件

json
// config.json
{
    "listeners": [{"address": "0.0.0.0", "port": 8080}],
    "threads_num": 4,
    "log": {
        "log_path": "./logs",
        "logfile_base_name": "drogon",
        "log_size_limit": 104857600
    },
    "app": {
        "document_root": "./static",
        "upload_path": "./uploads"
    }
}
cpp
int main() {
    drogon::app().loadConfigFile("config.json").run();
}

关键认知

Drogon 的高性能来自全异步 + 协程架构,每个请求不占用独立线程。协程控制器(HttpCoroController)是推荐用法,代码可读性接近同步。生产部署时配合 Nginx 反向代理处理静态文件和 SSL。

系统学习 C++ 生态,深入底层架构