Mikroszolgáltatások C++ nyelven. Fikció vagy valóság?

Mikroszolgáltatások C++ nyelven. Fikció vagy valóság?

Ebben a cikkben arról fogok beszélni, hogyan hoztam létre egy sablont (cookiecutter) és állítottam be egy környezetet egy REST API szolgáltatás írásához C++ nyelven a docker/docker-compose és a conan csomagkezelő segítségével.

A következő hackathon során, amelyen háttérfejlesztőként vettem részt, felmerült a kérdés, hogy mivel írjam meg a következő mikroszolgáltatást. Mindent, amit eddig írtam, én és az én írtam elvtárs Pythonban, mivel a kollégám ezen a területen jártas volt, és professzionálisan fejlesztette a backendeket, míg én általában beágyazott rendszerek fejlesztője voltam, és a nagyszerű és szörnyű C++-ban írtam, és most tanultam meg Pythont az egyetemen.

Így egy nagy terhelésű szolgáltatás megírásával álltunk szemben, melynek fő feladata a hozzá érkező adatok előfeldolgozása és adatbázisba írása volt. És egy újabb füstszünet után egy barátom azt javasolta, hogy C++ fejlesztőként írjam meg ezt a szolgáltatást a profik segítségével. Ezzel az érvel, hogy gyorsabb, produktívabb lesz, és általában a zsűri el lesz ragadtatva attól, hogyan tudjuk kezelni a csapat erőforrásait. Mire azt válaszoltam, hogy soha nem csináltam ilyeneket C++-ban, és a maradék 20+ órát nyugodtan fordíthatnám megfelelő könyvtárak keresésére, összeállítására és linkelésére. Egyszerűen fogalmazva, kiakadtam. Így döntöttünk, és nyugodtan befejeztünk mindent Pythonban.

Most, a kényszerű önizoláció során úgy döntöttem, kitalálom, hogyan írjak szolgáltatásokat C++ nyelven. Az első dolga a megfelelő könyvtár kiválasztása volt. A választásom esett POCO, mivel objektum-orientált stílusban íródott, és normál dokumentációval is büszkélkedhetett. Felmerült a kérdés az összeszerelési rendszer kiválasztásával kapcsolatban is. Eddig csak Visual Studio-val, IAR-rel és csupasz makefile-ekkel dolgoztam. És ezek a rendszerek egyike sem vonzott, mivel azt terveztem, hogy a teljes szolgáltatást egy dokkoló konténerben fogom futtatni. Aztán úgy döntöttem, hogy megpróbálom kitalálni a cmake-et és egy érdekes csomagkezelőt Conan. Ez a csomagkezelő lehetővé tette, hogy az összes függőséget egyetlen fájlban regisztrálja

conanfile.txt
[szükséges]poco/1.9.3
libpq/11.5

[generátorok] cmake

és egy egyszerű "conan install" paranccsal. telepítse a szükséges könyvtárakat. Természetesen ezen is változtatni kellett

CMakeLists.txt

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

Ezt követően elkezdtem keresni egy könyvtárat a PostgreSQL-lel való együttműködéshez, mivel ezzel kevés tapasztalatom volt, és a Python szolgáltatásaink is ezzel kommunikáltak. És tudod mit tanultam? A POCO-ban van! De a conan nem tudja, hogy a POCO-ban van, és nem tudja, hogyan kell felépíteni; van egy elavult konfigurációs fájl a tárolóban (erről a hibáról már írtam a POCO készítőinek). Ez azt jelenti, hogy másik könyvtárat kell keresnie.

És akkor a választásom egy kevésbé népszerű könyvtárra esett libpg. És hihetetlenül szerencsém volt, már a konanban volt, és még össze is szerelték és összeszerelték.

A következő lépés egy szolgáltatássablon megírása volt, amely képes feldolgozni a kéréseket.
A TemplateServerApp osztályunkat a Poco::Util::ServerApplication-től kell örökölnünk, és felül kell bírálnunk a fő metódust.

TemplateServerApp

#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;
}

A fő metódusban be kell állítani a paramétereket: port, szálak száma és a sor mérete. És ami a legfontosabb, meg kell adnia a bejövő kérések kezelőjét. Ez egy gyár létrehozásával történik

TemplateRequestHandlerFactory

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

Az én esetemben egyszerűen ugyanazt a kezelőt hozza létre minden alkalommal - TemplateServerAppHandler. Ide helyezhetjük üzleti logikánkat.

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();
    }
};

Létrehoztam egy osztálysablont is a PostgreSQL-lel való együttműködéshez. Az egyszerű SQL végrehajtásához, például egy tábla létrehozásához, létezik egy módszer ExecuteSQL(). Bonyolultabb lekérdezésekhez vagy adatlekéréshez kapcsolatot kell létesítenie ezen keresztül Kapcsolódás() és használja a libpg API-t. (Talán később kijavítom ezt az igazságtalanságot).

adatbázis

#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;
};

Az adatbázishoz való csatlakozáshoz szükséges összes paraméter a környezetből származik, ezért létre kell hozni és be kell állítani az .env fájlt is

.NS

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

Az összes kódot megtekintheti a címen github.

Mikroszolgáltatások C++ nyelven. Fikció vagy valóság?

És most jön a dockerfile és a docker-compose.yml megírásának utolsó szakasza. Hogy őszinte legyek, ez a legtöbb időt igénybe vette, és nem csak azért, mert noob vagyok, mert minden alkalommal újra kellett építeni a könyvtárakat, hanem a conan buktatói miatt is. Például ahhoz, hogy a conan letöltse, telepítse és felépítse a szükséges függőségeket, nem elég letöltenie a „conan install .-t”, át kell adnia a -s compiler.libcxx=libstdc++11 paramétert is, ellenkező esetben azt kockáztatja, hogy egy csomó hibát kap az alkalmazás összekapcsolási szakaszában. Több órája elakadtam ezzel a hibával, és remélem, hogy ez a cikk segít másoknak rövidebb idő alatt megoldani ezt a problémát.

Ezután, miután megírtam a docker-compose.yml fájlt, barátom tanácsára támogatást adtam hozzá cookie Cutter és most beszerezhet magának egy teljes értékű sablont a REST API szolgáltatáshoz C++ nyelven, testreszabott környezettel és telepített PostgreSQL-lel, egyszerűen a „cookiecutter” beírásával a konzolba. https://github.com/KovalevVasiliy/cpp_rest_api_template.git" Aztán „docker-compose up – build”.

Remélem, ez a sablon segíteni fog a kezdőknek a REST API-alkalmazások fejlesztésének nehéz útján a nagyszerű és hatékony, de olyan ügyetlen nyelven, mint a C++.
Ezen kívül nagyon ajánlom itt olvasni ezt cikk. Részletesebben elmagyarázza, hogyan kell dolgozni a POCO-val, és hogyan írhat saját REST API szolgáltatást.

Forrás: will.com

Hozzászólás