Microservizi in C++. Fiction o realità ?

Microservizi in C++. Fiction o realità ?

In questu articulu, parleraghju di cumu aghju creatu un mudellu (cookiecutter) è stabilisce un ambiente per scrive un serviziu API REST in C++ usendu docker/docker-compose è u gestore di pacchetti conan.

Duranti u prossimu hackathon, in quale aghju participatu cum'è sviluppatore di backend, a quistione hè stata di ciò chì aduprà per scrive u prossimu microserviziu. Tuttu ciò chì hè statu scrittu finu à avà hè statu scrittu da mè è u mo camarade in Python, postu chì u mo cullega era un espertu in questu campu è hà sviluppatu prufessiunali backends, mentre ch'e era in generale un sviluppatore di sistemi incrustati è hà scrittu in u grande è terribili C ++, è aghju appena amparatu Python à l'università.

Cusì, avemu statu affruntatu cù u compitu di scrive un serviziu high-load, u compitu principale di quale era di preprocessà i dati chì venenu à ellu è scrive in a basa di dati. È dopu à un'altra pausa di fumu, un amicu suggerì chì, cum'è sviluppatore C++, scrive stu serviziu cù i prufessiunali. Argumentendu questu hè chì serà più veloce, più pruduttivu, è in generale, u ghjuridiu serà piacè di cumu sapemu cumu gestisce e risorse di a squadra. À quale aghju rispostu chì ùn aghju mai fattu tali cose in C ++ è puderia facilmente dedicà l'ora di 20+ restante à a ricerca, a compilazione è a ligame di biblioteche adattate. Simply put, I chicken out. Hè ciò chì avemu decisu è cumpletamu tranquillamente tuttu in Python.

Avà, durante l'autoisolamentu furzatu, decisu di capisce cumu scrive servizii in C++. A prima cosa da fà era decide di una biblioteca adattata. A mo scelta hè cascata Poco, postu chì era scrittu in un stile orientatu à l'ughjettu è ancu vantava documentazione normale. Inoltre, a quistione hè stata di sceglie un sistema di assemblea. Finu à questu puntu, aghju travagliatu solu cù Visual Studio, IAR è bare makefiles. È nimu di sti sistemi m'hà attrattu, postu chì aghju pensatu à eseguisce tuttu u serviziu in un containeru docker. Allora decisu di pruvà à capisce cmake è un gestore di pacchetti interessanti conan. Stu gestore di pacchetti vi permette di registrà tutte e dipendenze in un schedariu

conanfile.txt
[necessita] poco/1.9.3
libpq/11.5

[generatori] cmake

è cù un cumandimu simplice "conan install". installà e librerie necessarie. Naturalmente, era ancu necessariu di fà cambiamenti

CMakeLists.txt

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

Dopu quì, aghju cuminciatu à circà una biblioteca per travaglià cù PostgreSQL, postu chì era quellu chì aghju avutu pocu sperienza di travaglià, è era ancu quellu chì i nostri servizii Python interagiscenu cù. E sapete ciò chì aghju amparatu ? Hè in POCO! Ma Conan ùn sapi micca chì hè in POCO è ùn sapi micca cumu custruisce; ci hè un schedariu di cunfigurazione anticu in u repository (aghju digià scrittu annantu à questu errore à i creatori di POCO). Questu significa chì avete da circà una altra biblioteca.

È tandu a mo scelta hè cascata nantu à una biblioteca menu pupulare libpg. È eru incredibbilmente furtunatu, era digià in conan è era ancu esse assemblatu è assemblatu.

U passu prossimu era di scrive un mudellu di serviziu chì pò processà e dumande.
Avemu da eredite a nostra classe TemplateServerApp da Poco::Util::ServerApplication è annullà u metudu principale.

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

In u metudu principale, avemu da stabilisce i paràmetri: u portu, u numeru di fili è a dimensione di a fila. È più impurtante, duvete specificà un gestore per e richieste entrate. Questu hè fattu da a creazione di una fabbrica

TemplateRequestHandlerFactory

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

In u mo casu, simpricimenti crea u listessu gestore ogni volta - TemplateServerAppHandler. Questu hè induve pudemu mette a nostra logica cummerciale.

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

Aghju ancu creatu un mudellu di classi per travaglià cù PostgreSQL. Per fà SQL simplice, cum'è a creazione di una tavola, ci hè un metudu ExecuteSQL (). Per dumande più cumplesse o ricuperazione di dati, avete da ottene una cunnessione via GetConnection () è utilizate l'API libpg. (Forse dopu correraghju sta inghjustizia).

Archivio

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

Tutti i paràmetri per cunnette à a basa di dati sò pigliati da l'ambienti, cusì avete bisognu di creà è cunfigurà u schedariu .env.

.env

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

Pudete vede tuttu u codice à github.

Microservizi in C++. Fiction o realità ?

È avà vene l'ultima tappa di scrive u dockerfile è docker-compose.yml. Per esse onestu, questu hà pigliatu a maiò parte di u tempu, è micca solu perchè sò un noob, perchè era necessariu di ricustruisce e biblioteche ogni volta, ma per via di i picciotti di conan. Per esempiu, per cunan per scaricà, installà è custruisce e dipendenze necessarie, ùn hè micca abbastanza per scaricà "conan install .", hè ancu bisognu di passà u paràmetru -s compiler.libcxx=libstdc++ 11, altrimenti. rischiate di ottene una mansa di errori in u stadiu di ligame di a vostra applicazione. Sò statu chjappu cù questu errore per parechje ore è speru chì questu articulu aiuterà altre persone à risolve stu prublema in menu tempu.

Dopu, dopu avè scrittu docker-compose.yml, nantu à i cunsiglii di u mo amicu, aghju aghjustatu supportu cookiecutter è avà pudete uttene un mudellu cumpletu per un serviziu API REST in C ++, cù un ambiente persunalizatu, è PostgreSQL installatu, solu inserendu "cookiecutter" in a cunsola. https://github.com/KovalevVasiliy/cpp_rest_api_template.git" E poi "docker-compose up -build".

Spergu chì stu mudellu aiuterà i principianti nantu à a so strada difficiule di sviluppà l'applicazioni REST API in u grande è putente, ma una lingua cusì goffa cum'è C ++.
Inoltre, vi cunsigliu assai di leghje quì questu articulu. Spiega in più dettagliu cumu travaglià cù POCO è scrive u vostru propiu serviziu REST API.

Source: www.habr.com

Add a comment