Mikropakalpojumi C++ valodā. Daiļliteratūra vai realitāte?

Mikropakalpojumi C++ valodā. Daiļliteratūra vai realitāte?

Å ajā rakstā es runāŔu par to, kā es izveidoju veidni (cookiecutter) un izveidoju vidi REST API pakalpojuma rakstÄ«Å”anai programmā C++, izmantojot docker/docker-compose un conan pakotņu pārvaldnieku.

Nākamajā hakatonā, kurā piedalÄ«jos kā aizmugursistēmas izstrādātājs, radās jautājums par to, ar ko rakstÄ«t nākamo mikroservisu. Viss, kas lÄ«dz Å”im ir rakstÄ«ts, esmu rakstÄ«ts es un mani biedrs Python, jo mans kolēģis bija eksperts Å”ajā jomā un profesionāli izstrādāja backends, savukārt es parasti biju iegulto sistēmu izstrādātājs un rakstÄ«ju lieliskā un briesmÄ«gā C++ valodā, un es tikko universitātē apguvu Python.

Tātad, mēs saskārāmies ar uzdevumu uzrakstÄ«t augstas slodzes pakalpojumu, kura galvenais uzdevums bija iepriekÅ” apstrādāt tajā ienākoÅ”os datus un ierakstÄ«t tos datu bāzē. Un pēc kārtējās dÅ«mu pauzes draugs ieteica man kā C++ izstrādātājam uzrakstÄ«t Å”o pakalpojumu, izmantojot profesionāļus. Tas ir arguments, ka tas bÅ«s ātrāk, produktÄ«vāk, un kopumā žūrija bÅ«s sajÅ«smā par to, kā mēs zinām, kā pārvaldÄ«t komandas resursus. Uz ko es atbildēju, ka nekad neesmu darÄ«jis tādas lietas C++ valodā un atlikuŔās 20+ stundas varētu viegli veltÄ«t piemērotu bibliotēku meklÄ“Å”anai, apkopoÅ”anai un saistÄ«Å”anai. VienkārŔāk sakot, es sastingu. Tā mēs nolēmām un mierÄ«gi visu pabeidzām Python.

Tagad, piespiedu paÅ”izolācijas laikā, es nolēmu izdomāt, kā rakstÄ«t pakalpojumus C++ valodā. Vispirms bija jāizlemj par piemērotu bibliotēku. Mana izvēle krita Poco, jo tas bija uzrakstÄ«ts objektorientētā stilā un arÄ« lepojās ar normālu dokumentāciju. Tāpat radās jautājums par montāžas sistēmas izvēli. LÄ«dz Å”im esmu strādājis tikai ar Visual Studio, IAR un tukÅ”iem makefiliem. Un neviena no Ŕīm sistēmām mani neuzrunāja, jo es plānoju palaist visu pakalpojumu doka konteinerā. Tad es nolēmu mēģināt izdomāt cmake un interesantu pakotņu pārvaldnieku Konans. Å is pakotņu pārvaldnieks ļāva reÄ£istrēt visas atkarÄ«bas vienā failā

conanfile.txt
[nepiecieŔams]poco/1.9.3
libpq/11.5

[Ä£eneratori] cmake

un ar vienkārÅ”u komandu "conan install." instalējiet nepiecieÅ”amās bibliotēkas. Protams, bija arÄ« jāveic izmaiņas

CMakeLists.txt

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

Pēc tam es sāku meklēt bibliotēku darbam ar PostgreSQL, jo ar to man bija maz pieredzes, un ar to arÄ« mijiedarbojās mÅ«su Python pakalpojumi. Un vai jÅ«s zināt, ko es uzzināju? Tas ir POCO! Bet Conan nezina, ka tas atrodas POCO, un nezina, kā to izveidot; repozitorijā ir novecojis konfigurācijas fails (es jau rakstÄ«ju par Å”o kļūdu POCO veidotājiem). Tas nozÄ«mē, ka jums bÅ«s jāmeklē cita bibliotēka.

Un tad mana izvēle krita uz kādu mazāk populāru bibliotēku libpg. Un man neticami paveicās, tas jau bija gatavībā un pat tika montēts un montēts.

Nākamais solis bija uzrakstīt pakalpojuma veidni, kas var apstrādāt pieprasījumus.
Mums ir jāmanto sava TemplateServerApp klase no Poco::Util::ServerApplication un jāignorē galvenā metode.

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

Galvenajā metodē mums jāiestata parametri: ports, pavedienu skaits un rindas lielums. Un pats galvenais, jums ir jānorāda ienākoÅ”o pieprasÄ«jumu apstrādātājs. Tas tiek darÄ«ts, izveidojot rÅ«pnÄ«cu

TemplateRequestHandlerFactory

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

Manā gadÄ«jumā tas vienkārÅ”i katru reizi izveido vienu un to paÅ”u apdarinātāju - TemplateServerAppHandler. Å eit mēs varam izvietot savu biznesa loÄ£iku.

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

Es arÄ« izveidoju klases veidni darbam ar PostgreSQL. Lai veiktu vienkārÅ”u SQL, piemēram, izveidotu tabulu, ir metode ExecuteSQL(). Sarežģītākiem vaicājumiem vai datu izguvei jums bÅ«s jāiegÅ«st savienojums, izmantojot GetConnection() un izmantojiet libpg API. (VarbÅ«t vēlāk Å”o netaisnÄ«bu izlaboÅ”u).

Datubāze

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

Visi parametri savienojumam ar datu bāzi tiek ņemti no vides, tāpēc jāizveido un jākonfigurē arī .env fails

.env

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

Visu kodu varat redzēt vietnē github.

Mikropakalpojumi C++ valodā. Daiļliteratūra vai realitāte?

Un tagad ir pēdējais dokumenta dockerfile un docker-compose.yml rakstÄ«Å”anas posms. GodÄ«gi sakot, tas aizņēma lielāko daļu laika, un ne tikai tāpēc, ka esmu necilvēks, jo katru reizi bija nepiecieÅ”ams atjaunot bibliotēkas, bet arÄ« konana kļūmju dēļ. Piemēram, lai conan lejupielādētu, instalētu un izveidotu nepiecieÅ”amās atkarÄ«bas, nepietiek tikai ar ā€œconan install .ā€ lejupielādi, tam ir arÄ« jānodod parametrs -s compiler.libcxx=libstdc++11, pretējā gadÄ«jumā. jÅ«s riskējat iegÅ«t virkni kļūdu lietojumprogrammas saistÄ«Å”anas posmā. Es esmu iestrēdzis ar Å”o kļūdu vairākas stundas, un es ceru, ka Å”is raksts palÄ«dzēs citiem cilvēkiem atrisināt Å”o problēmu Ä«sākā laikā.

Pēc tam, kad es uzrakstÄ«ju docker-compose.yml, pēc sava drauga ieteikuma pievienoju atbalstu cepumu griezējs un tagad varat iegÅ«t pilnvērtÄ«gu REST API pakalpojuma veidni C++ valodā ar pielāgotu vidi un instalētu PostgreSQL, vienkārÅ”i ievadot konsolē ā€œcookiecutterā€. https://github.com/KovalevVasiliy/cpp_rest_api_template.git" Un pēc tam ā€œdocker-compose up ā€“ buildā€.

Es ceru, ka Ŕī veidne palÄ«dzēs iesācējiem grÅ«tajā ceļā, izstrādājot REST API lietojumprogrammas lieliskajā un jaudÄ«gajā, taču tik neveiklā valodā kā C++.
Turklāt es ļoti iesaku lasīt Ŕeit Ŕis rakstu. Tajā ir sīkāk paskaidrots, kā strādāt ar POCO un izveidot savu REST API pakalpojumu.

Avots: www.habr.com

Pievieno komentāru