Mikrozerbitzuak C++-n. Fikzioa ala errealitatea?

Mikrozerbitzuak C++-n. Fikzioa ala errealitatea?

Artikulu honetan txantiloi bat (cookiecutter) sortu eta C++-n REST API zerbitzu bat idazteko ingurune bat nola konfiguratu docker/docker-compose eta conan pakete kudeatzailea erabiliz hitz egingo dut.

Hurrengo hackatoian, zeinetan backend garatzaile gisa parte hartu nuen, hurrengo mikrozerbitzua idazteko zer erabili behar zen galdera sortu zen. Orain arte idatzitako guztia nik eta nik idatzi dugu kamarada Python-en, nire lankidea arlo honetan aditua zenez eta profesionalki backendak garatzen zituenez, orokorrean txertatutako sistemen garatzaile bat nintzen eta C++ bikain eta ikaragarrian idazten nuen bitartean, eta Python unibertsitatean ikasi berri nuen.

Beraz, karga handiko zerbitzu bat idazteko zereginaren aurrean geunden, zeinaren zeregin nagusia bertara iristen ziren datuak aldez aurretik prozesatzea eta datu-basean idaztea zen. Eta beste ke-etenaldi baten ondoren, lagun batek iradoki zidan, C++ garatzaile gisa, zerbitzu hau profesionalak erabiliz idaztea. Hori argudiatuta, azkarragoa, produktiboagoa izango da eta, oro har, epaimahaia pozik egongo da taldearen baliabideak kudeatzen dakigunarekin. Horri erantzun nion ez nuela inoiz horrelakorik egin C++-n eta gainerako 20 ordu baino gehiago erraz eman niezaiokeela liburutegi egokiak bilatu, konpilatu eta lotzera. Besterik gabe, oilaskoa atera nintzen. Horixe erabaki genuen eta lasaitasunez osatu genuen guztia Pythonen.

Orain, behartutako auto-isolamenduan, zerbitzuak C++-n nola idatzi asmatzea erabaki nuen. Lehenik eta behin liburutegi egoki bat erabakitzea izan zen. Nire aukera erori zen POCO, objektuetara zuzendutako estiloan idatzia baita eta dokumentazio normala ere harrotzen zuen. Era berean, muntaketa sistema bat aukeratzearen inguruko galdera sortu zen. Orain arte Visual Studio, IAR eta bare makefiles-ekin baino ez dut lan egin. Eta sistema horietako batek ere ez ninduen erakartzen, zerbitzu osoa docker edukiontzi batean exekutatzeko asmoa nuen eta. Orduan cmake eta pakete kudeatzaile interesgarri bat asmatzen saiatzea erabaki nuen conan. Pakete-kudeatzaile honek menpekotasun guztiak fitxategi batean erregistratzeko aukera eman zuen

conanfile.txt
[behar du]poco/1.9.3
libpq/11.5

[sorgailuak] cmake

eta komando sinple batekin "conan install ." beharrezko liburutegiak instalatu. Jakina, aldaketak egitea ere beharrezkoa zen

CMakeLists.txt

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

Horren ostean, PostgreSQL-rekin lan egiteko liburutegi baten bila hasi nintzen, lanean esperientzia gutxi nuen hura baitzen, eta gure Python zerbitzuek elkarrekin egiten zutena ere bai. Eta ba al dakizu zer ikasi nuen? POCO-n dago! Baina conanek ez daki POCOn dagoenik eta ez daki nola eraiki; zaharkitutako konfigurazio fitxategi bat dago biltegian (dagoeneko idatzi diet errore honi buruz POCOren sortzaileei). Horrek esan nahi du beste liburutegi bat bilatu beharko duzula.

Eta orduan nire aukera ez hain ezaguna den liburutegi batean erori zen libpg. Eta zorte izugarria izan nuen, dagoeneko konan zegoen eta muntatzen eta muntatzen ari ziren ere.

Hurrengo urratsa eskaerak prozesatu ditzakeen zerbitzu txantiloia idaztea izan zen.
Poco::Util::ServerApplication-etik gure TemplateServerApp klasea heredatu eta metodo nagusia gainidatzi behar dugu.

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

Metodo nagusian parametroak ezarri behar ditugu: ataka, hari kopurua eta ilararen tamaina. Eta garrantzitsuena, sarrerako eskaeren kudeatzaile bat zehaztu behar duzu. Hau fabrika bat sortuz egiten da

TemplateRequestHandlerFactory

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

Nire kasuan, kudeatzaile bera sortzen du aldi bakoitzean - TemplateServerAppHandler. Hor kokatu dezakegu gure negozio-logika.

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-ekin lan egiteko klase txantiloia ere sortu nuen. SQL sinplea egiteko, esate baterako, taula bat sortzeko, metodo bat dago ExecuteSQL(). Kontsulta konplexuagoak edo datuak berreskuratzeko, bidezko konexioa lortu beharko duzu GetConnection() eta erabili libpg APIa. (Agian geroago zuzenduko dut injustizia hori).

Datu-basea

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

Datu-basera konektatzeko parametro guztiak ingurunetik hartzen dira, beraz, .env fitxategia ere sortu eta konfiguratu behar duzu

.env

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

Kode guztia hemen ikus dezakezu github.

Mikrozerbitzuak C++-n. Fikzioa ala errealitatea?

Eta orain dockerfile eta docker-compose.yml idazteko azken etapa dator. Egia esateko, honek denbora gehiena hartzen zuen, eta ez bakarrik noob bat naizelako, liburutegiak berreraikitzea beharrezkoa zelako aldiro, baizik eta conan-en zuloengatik. Adibidez, conan-ek beharrezko mendekotasunak deskargatu, instalatu eta eraikitzeko, ez da nahikoa "conan install ." deskargatzea, -s compiler.libcxx=libstdc++11 parametroa ere pasatu behar du, bestela. Zure aplikazioa lotzeko fasean errore mordo bat izateko arriskua duzu. Hainbat orduz akats honekin trabatuta egon naiz eta artikulu honek beste pertsona batzuei arazo hau denbora gutxiagoan konpontzen lagunduko diela espero dut.

Jarraian, docker-compose.yml idatzi ondoren, nire lagunaren aholkuez, laguntza gehitu nuen cookie-ebakitzailea eta orain C++-n REST API zerbitzu baterako txantiloi oso bat lor dezakezu, ingurune pertsonalizatu batekin eta PostgreSQL instalatuta, kontsolan "cookiecutter" sartuta. https://github.com/KovalevVasiliy/cpp_rest_api_template.git" Eta gero "docker-compose up β€”build".

Txantiloi honek REST API aplikazioak garatzeko bide zailean hasiberriei lagunduko diela espero dut, C++ bezalako lengoaia handi eta indartsu batean, baina hain traketsa.
Gainera, hemen irakurtzea gomendatzen dut hau Artikulu. Xehetasun handiagoz azaltzen du POCOrekin nola lan egin eta zure REST API zerbitzua nola idatzi.

Iturria: www.habr.com

Gehitu iruzkin berria