C++ 中的微服務。 小說還是現實?

C++ 中的微服務。 小說還是現實?

在本文中,我將討論如何建立範本 (cookiecutter) 並設定環境,以便使用 docker/docker-compose 和 conan 套件管理器在 C++ 中編寫 REST API 服務。

在我作為後端開發人員參加的下一次黑客馬拉松中,出現了關於使用什麼來編寫下一個微服務的問題。到目前為止所寫的所有內容都是我和我的朋友寫的 同志 我的同事是這個領域的專家,專業開發後端,而我通常是嵌入式系統開發人員,用偉大而可怕的C++編寫,而我剛剛在大學學習了Python。

因此,我們面臨著編寫高負載服務的任務,其主要任務是預處理傳入的資料並將其寫入資料庫。在又一次冒煙之後,一位朋友建議我,作為一名 C++ 開發人員,使用專業人士來編寫此服務。我認為這樣做會更快、更有效率,而且總的來說,評審團會對我們如何管理團隊資源感到高興。我回答說我從來沒有在 C++ 中做過這樣的事情,並且可以輕鬆地將剩餘的 20 多個小時用於搜尋、編譯和連結合適的程式庫。簡單地說,我退縮了。我們就這樣決定了,並平靜地用Python完成了一切。

現在,在強制自我隔離期間,我決定弄清楚如何用 C++ 編寫服務。要做的第一件事是決定一個合適的函式庫。我的選擇落到了 POCO,因為它是用物件導向的風格編寫的,並且還擁有正常的文檔。此外,也出現了有關選擇組裝系統的問題。到目前為止,我只使用過 Visual Studio、IAR 和裸 makefile。這些系統都不吸引我,因為我計劃在 Docker 容器中執行整個服務。然後我決定嘗試找出 cmake 和一個有趣的套件管理器 柯南。該套件管理器允許您在一個檔案中註冊所有依賴項

柯南文件.txt
[requires] poco/1.9.3
libpq/11.5

[generators] cmake

並使用一個簡單的命令“conan install”。安裝必要的庫。當然,也需要做出改變

CMakeLists.txt

include(build/conanbuildinfo.cmake)
conan_basic_setup()
target_link_libraries(<target_name> ${CONAN_LIBS})

之後,我開始尋找一個與 PostgreSQL 一起使用的函式庫,因為我幾乎沒有使用它的經驗,而且它也是我們的 Python 服務與之互動的函式庫。你知道我學到了什麼嗎?就在POCO!但柯南不知道它在 POCO 中,也不知道如何構建它;存儲庫中有一個過時的配置文件(我已經向 POCO 的創建者寫了有關此錯誤的信息)。這意味著您將不得不尋找另一個圖書館。

然後我選擇了一個不太受歡迎的圖書館 庫文件庫。我非常幸運,它已經在柯南中了,甚至正在組裝和組裝。

下一步是編寫一個可以處理請求的服務模板。
我們必須從 Poco::Util::ServerApplication 繼承 TemplateServerApp 類別並重寫 main 方法。

模板伺服器應用程式

#pragma once

#include <string>
#include <vector>
#include <Poco/Util/ServerApplication.h>

class TemplateServerApp : public Poco::Util::ServerApplication
{
    protected:
        int main(const std::vector<std::string> &);
};

int TemplateServerApp::main(const vector<string> &)
{
    HTTPServerParams* pParams = new HTTPServerParams;

    pParams->setMaxQueued(100);
    pParams->setMaxThreads(16);

    HTTPServer s(new TemplateRequestHandlerFactory, ServerSocket(8000), pParams);

    s.start();
    cerr << "Server started" << endl;

    waitForTerminationRequest();  // wait for CTRL-C or kill

    cerr << "Shutting down..." << endl;
    s.stop();

    return Application::EXIT_OK;
}

在main方法中我們必須設定參數:連接埠、執行緒數和佇列大小。最重要的是,您必須為傳入請求指定一個處理程序。這是透過創建工廠來完成的

模板請求處理工廠

class TemplateRequestHandlerFactory : public HTTPRequestHandlerFactory
{
public:
    virtual HTTPRequestHandler* createRequestHandler(const HTTPServerRequest & request)
    {
        return new TemplateServerAppHandler;
    }
};

就我而言,它只是每次都創建相同的處理程序 - TemplateServerAppHandler。這是我們可以放置業務邏輯的地方。

模板伺服器應用程式處理程序

class TemplateServerAppHandler : public HTTPRequestHandler
{
public:
    void handleRequest(HTTPServerRequest &req, HTTPServerResponse &resp)
    {
        URI uri(req.getURI());
        string method = req.getMethod();

        cerr << "URI: " << uri.toString() << endl;
        cerr << "Method: " << req.getMethod() << endl;

        StringTokenizer tokenizer(uri.getPath(), "/", StringTokenizer::TOK_TRIM);
        HTMLForm form(req,req.stream());

        if(!method.compare("POST"))
        {
            cerr << "POST" << endl;
        }
        else if(!method.compare("PUT"))
        {
            cerr << "PUT" << endl;
        }
        else if(!method.compare("DELETE"))
        {
            cerr << "DELETE" << endl;
        }

        resp.setStatus(HTTPResponse::HTTP_OK);
        resp.setContentType("application/json");
        ostream& out = resp.send();

        out << "{"hello":"heh"}" << endl;
        out.flush();
    }
};

我還創建了一個類別模板​​來使用 PostgreSQL。要執行簡單的SQL,例如建立表,有一個方法 執行SQL()。對於更複雜的查詢或資料檢索,您必須透過以下方式取得連接 取得連線() 並使用 libpg API。 (也許以後我會糾正這個不公平的現象)。

數據庫

#pragma once

#include <memory>
#include <mutex>
#include <libpq-fe.h>

class Database
{
public:
    Database();
    std::shared_ptr<PGconn> GetConnection() const;
    bool ExecuteSQL(const std::string& sql);

private:
    void establish_connection();
    void LoadEnvVariables();

    std::string m_dbhost;
    int         m_dbport;
    std::string m_dbname;
    std::string m_dbuser;
    std::string m_dbpass;

    std::shared_ptr<PGconn>  m_connection;
};

連接資料庫的所有參數均取自環境,因此還需要建立並配置.env檔案

.ENV

DATABASE_NAME=template
DATABASE_USER=user
DATABASE_PASSWORD=password
DATABASE_HOST=postgres
DATABASE_PORT=5432

您可以在以下位置查看所有程式碼 github。

C++ 中的微服務。 小說還是現實?

現在是編寫 dockerfile 和 docker-compose.yml 的最後階段。說實話,這花了大部分時間,不僅因為我是菜鳥,因為每次都需要重建庫,還因為柯南的陷阱。例如,為了讓conan下載、安裝和構建必要的依賴項,僅下載“conan install.”是不夠的,還需要傳遞-s compiler.libcxx=libstdc++11參數,否則您可能會在應用程序的鏈接階段遇到一堆錯誤。我已經被這個錯誤困擾了幾個小時,我希望這篇文章能幫助其他人在更短的時間內解決這個問題。

接下來,寫完docker-compose.yml後,根據朋友的建議,我添加了支持 小甜餅 現在,您只需在控制台中輸入“cookiecutter”,即可獲得 C++ 中的 REST API 服務的成熟模板,其中包含自訂環境並安裝了 PostgreSQL https://github.com/KovalevVasiliy/cpp_rest_api_template.git」然後“docker-compose up —build”。

我希望這個模板能夠幫助初學者走上使用 C++ 這樣強大但笨拙的語言開發 REST API 應用程式的艱難道路。
另外,我強烈推薦在這裡閱讀 文章。它更詳細地解釋瞭如何使用 POCO 並編寫您自己的 REST API 服務。

來源: www.habr.com

添加評論