Mikroservizzi f'C++. Finzjoni jew realtà?

Mikroservizzi f'C++. Finzjoni jew realtà?

F'dan l-artikolu ser nitkellem dwar kif ħloqt mudell (cookiecutter) u waqqaf ambjent għall-kitba ta 'servizz REST API f'C++ billi tuża docker/docker-compose u l-maniġer tal-pakkett conan.

Matul l-hackathon li jmiss, li fih ipparteċipajt bħala żviluppatur backend, qamet il-mistoqsija dwar x'għandek tuża biex tikteb il-mikroservizz li jmiss. Dak kollu li nkiteb s’issa nkiteb jien u tiegħi sħabu f'Python, peress li l-kollega tiegħi kien espert f'dan il-qasam u żviluppa backends professjonalment, filwaqt li ġeneralment kont żviluppatur ta' sistemi integrati u ktibt fis-C++ kbir u terribbli, u għadni kemm tgħallimt Python fl-università.

Għalhekk, konna ffaċċjati bil-kompitu li niktbu servizz ta 'tagħbija għolja, li l-kompitu ewlieni tiegħu kien li tipproċessa minn qabel id-dejta li waslet għaliha u niktbuha fid-database. U wara waqfa oħra tad-duħħan, ħabib issuġġerixxa li jien, bħala żviluppatur C++, nikteb dan is-servizz billi tuża l-vantaġġi. Jargumentaw dan huwa li se jkun aktar mgħaġġel, aktar produttiv, u b'mod ġenerali, il-ġurija se tkun kuntenta b'kif nafu kif namministraw ir-riżorsi tat-tim. Għalihom wieġeb li qatt ma kont għamilt affarijiet bħal dawn f'C++ u stajt faċilment niddedika l-20+ siegħa li fadal biex infittex, niġbor u ngħaqqad libreriji xierqa. Fi kliem sempliċi, I chicken out. Dak hu li ddeċidejna u lestejna kollox bil-kalma f'Python.

Issa, matul l-awto-iżolament sfurzat, iddeċidejt li nifhem kif tikteb servizzi f'C++. L-ewwel ħaġa li għandek tagħmel kienet tiddeċiedi fuq librerija xierqa. L-għażla tiegħi waqgħet fuq POCO, peress li kienet miktuba fi stil orjentat lejn l-oġġetti u wkoll tiftaħar dokumentazzjoni normali. Ukoll, qamet il-mistoqsija dwar l-għażla ta 'sistema ta' assemblaġġ. Sa dan il-punt ħdimt biss ma' Visual Studio, IAR u makefiles vojta. U l-ebda waħda minn dawn is-sistemi ma appellatli, peress li ppjanajt li nħaddem is-servizz kollu f'kontenitur docker. Imbagħad iddeċidejt li nipprova nsib cmake u maniġer tal-pakketti interessanti conan. Dan il-maniġer tal-pakkett ippermettilek tirreġistra d-dipendenzi kollha f'fajl wieħed

conanfile.txt
[jeħtieġ]poco/1.9.3
libpq/11.5

[ġeneraturi] cmake

u bi kmand sempliċi "conan install ." tinstalla l-libreriji meħtieġa. Naturalment, kien meħtieġ ukoll li jsiru bidliet

CMakeLists.txt

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

Wara dan, bdejt infittex librerija biex naħdem mal-PostgreSQL, peress li kienet dik li kelli ftit esperjenza naħdem magħha, u kienet ukoll dik li s-servizzi Python tagħna jinteraġixxu magħha. U taf x’tgħallimt? Huwa f'POCO! Imma conan ma jafx li jinsab f'POCO u ma jafx kif jibniha; hemm fajl ta 'konfigurazzjoni skadut fir-repożitorju (diġà ktibt dwar dan l-iżball lill-ħallieqa ta' POCO). Dan ifisser li jkollok tfittex librerija oħra.

U mbagħad l-għażla tiegħi waqgħet fuq librerija inqas popolari libpg. U kont oerhört xortik tajba, kien diġà f'conan u kien saħansitra qed jiġi mmuntat u mmuntat.

Il-pass li jmiss kien li tikteb mudell ta 'servizz li jista' jipproċessa t-talbiet.
Irridu nirtitu l-klassi TemplateServerApp tagħna minn Poco::Util::ServerApplication u nissuperaw il-metodu prinċipali.

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

Fil-metodu ewlieni għandna nissettjaw il-parametri: port, numru ta 'ħjut u daqs tal-kju. U l-aktar importanti, trid tispeċifika handler għal talbiet deħlin. Dan isir billi tinħoloq fabbrika

TemplateRequestHandlerFactory

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

Fil-każ tiegħi, sempliċement toħloq l-istess handler kull darba - TemplateServerAppHandler. Dan huwa fejn nistgħu npoġġu l-loġika tan-negozju tagħna.

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

Ħloqt ukoll mudell ta' klassi biex naħdem ma' PostgreSQL. Biex twettaq SQL sempliċi, bħall-ħolqien ta 'tabella, hemm metodu ExecuteSQL(). Għal mistoqsijiet aktar kumplessi jew irkupru tad-dejta, ser ikollok tikseb konnessjoni permezz GetConnection() u uża l-API libpg. (Forsi aktar tard se nikkoreġi din l-inġustizzja).

Database

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

Il-parametri kollha għall-konnessjoni mad-database jittieħdu mill-ambjent, għalhekk għandek bżonn ukoll toħloq u tikkonfigura l-fajl .env

.a V

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

Tista' tara l-kodiċi kollu fuq github.

Mikroservizzi f'C++. Finzjoni jew realtà?

U issa jasal l-istadju finali tal-kitba tad-dockerfile u docker-compose.yml. Biex inkun onest, dan ħa l-biċċa l-kbira tal-ħin, u mhux biss għax jien noob, għax kien meħtieġ li jerġgħu jinbnew il-libreriji kull darba, iżda minħabba l-iżvantaġġi ta 'conan. Pereżempju, sabiex conan tniżżel, jinstalla u jibni d-dipendenzi meħtieġa, mhuwiex biżżejjed li tniżżel "conan install .", jeħtieġ ukoll li jgħaddi l-parametru -s compiler.libcxx=libstdc++11, inkella tirriskja li tikseb mazz ta 'żbalji fl-istadju ta' rabta tal-applikazzjoni tiegħek. Ilni mwaħħla b'dan l-iżball għal diversi sigħat u nittama li dan l-artikolu jgħin lil nies oħra jsolvu din il-problema f'inqas ħin.

Sussegwentement, wara li ktibt docker-compose.yml, fuq parir ta 'ħabib tiegħi, żidt appoġġ cookiecutter u issa tista' tikseb lilek innifsek mudell sħiħ għal servizz REST API f'C++, b'ambjent personalizzat, u PostgreSQL installat, sempliċiment billi ddaħħal "cookiecutter" fil-console. https://github.com/KovalevVasiliy/cpp_rest_api_template.git" U mbagħad "docker-compose up -build".

Nittama li dan il-mudell se jgħin lill-jibdew fit-triq diffiċli tagħhom biex jiżviluppaw applikazzjonijiet REST API fil-kbir u b'saħħtu, iżda lingwa daqshekk goff bħal C++.
Ukoll, nirrakkomanda ħafna li taqra hawn dan artikolu. Jispjega f'aktar dettall kif taħdem ma 'POCO u tikteb is-servizz REST API tiegħek stess.

Sors: www.habr.com

Żid kumment