Mikrotsjinsten yn C++. Fiksje of realiteit?

Mikrotsjinsten yn C++. Fiksje of realiteit?

Yn dit artikel sil ik prate oer hoe't ik in sjabloan makke (cookiecutter) en in omjouwing ynstelle foar it skriuwen fan in REST API-tsjinst yn C ++ mei docker/docker-compose en de conan-pakketbehearder.

Tidens de folgjende hackathon, dêr't ik as backend-ûntwikkelder oan meidie, kaam de fraach oer wat te brûken om de folgjende mikrotsjinst te skriuwen. Alles wat oant no ta skreaun is, is skreaun troch my en myn kameraad yn Python, sûnt myn kollega wie in ekspert op dit mêd en profesjoneel ûntwikkele backends, wylst ik wie oer it algemien in ynbêde systemen ûntwikkeler en skreau yn de grutte en ferskriklike C ++, en ik krekt learde Python op universiteit.

Dat, wy waarden konfrontearre mei de taak fan it skriuwen fan in tsjinst mei hege lading, wêrfan de haadtaak wie om de gegevens dy't derby komme foar te ferwurkjen en te skriuwen nei de databank. En nei in oare reekpauze suggerearre in freon dat ik, as C++-ûntwikkelder, dizze tsjinst skriuw mei de profs. Dit argumintearje is dat it rapper, produktiver sil wêze, en yn 't algemien sil de sjuery bliid wêze mei hoe't wy witte hoe't wy de middels fan it team kinne beheare. Dêrop antwurde ik dat ik sokke dingen noait dien hie yn C++ en de oerbleaune 20+ oeren maklik besteegje koe oan it sykjen, kompilearjen en keppeljen fan gaadlike bibleteken. Simply sette, ik kip út. Dat hawwe wy besletten en rêstich alles yn Python ôfmakke.

No, tidens de twongen selsisolaasje, besleat ik út te finen hoe't jo tsjinsten yn C ++ skriuwe kinne. It earste ding om te dwaan wie beslute oer in geskikte biblioteek. Myn kar foel op poco, om't it skreaun is yn in objekt-rjochte styl en hat ek gewoane dokumintaasje. Ek ûntstie de fraach oer it kiezen fan in assemblagesysteem. Oant dit punt haw ik allinich wurke mei Visual Studio, IAR en bleate makefiles. En net ien fan dizze systemen spruts my oan, om't ik fan plan wie om de hiele tsjinst yn in docker-kontener út te fieren. Doe besleat ik om te besykjen cmake en in nijsgjirrige pakketbehearder út te finen conan. Dizze pakketbehearder liet jo alle ôfhinklikens yn ien bestân registrearje

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

[generators] cmake

en mei in ienfâldich kommando "conan install." ynstallearje de nedige biblioteken. Fansels wie it ek nedich om feroarings oan te bringen

CMakeLists.txt

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

Dêrnei begon ik op syk nei in bibleteek om te wurkjen mei PostgreSQL, om't it dejinge wie wêr't ik net folle ûnderfining mei hie, en it wie ek dejinge dy't ús Python-tsjinsten ynteraksje mei. En witsto wat ik leard haw? It is yn POCO! Mar conan wit net dat it yn POCO is en wit net hoe't it moat bouwe; d'r is in ferâldere konfiguraasjetriem yn 'e repository (ik haw al skreaun oer dizze flater oan' e makkers fan POCO). Dit betsjut dat jo nei in oare bibleteek moatte sykje.

En doe foel myn kar op in minder populêre bibleteek libpg. En ik wie ongelooflijk gelok, it wie al yn conan en waard sels gearstald en gearstald.

De folgjende stap wie om in tsjinstsjabloan te skriuwen dat fersiken kin ferwurkje.
Wy moatte ús TemplateServerApp-klasse erve fan Poco :: Util :: ServerApplication en de haadmetoade oerskriuwe.

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

Yn 'e haadmetoade moatte wy de parameters ynstelle: poarte, oantal triedden en wachtrige grutte. En it wichtichste, jo moatte in handler opjaan foar ynkommende oanfragen. Dit wurdt dien troch it meitsjen fan in fabryk

TemplateRequestHandlerFactory

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

Yn myn gefal makket it gewoan elke kear deselde handler - TemplateServerAppHandler. Dit is wêr't wy ús bedriuwslogika kinne pleatse.

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

Ik haw ek in klassesjabloan makke om te wurkjen mei PostgreSQL. Om ienfâldige SQL út te fieren, lykas it meitsjen fan in tabel, is d'r in metoade ExecuteSQL(). Foar mear komplekse fragen of gegevens opheljen moatte jo in ferbining krije fia GetConnection() en brûk de libpg API. (Miskien sil ik letter dit ûnrjocht korrigearje).

Databank

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

Alle parameters foar it ferbinen mei de databank wurde út 'e omjouwing nommen, dus jo moatte ek it .env-bestân oanmeitsje en konfigurearje

.en V

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

Jo kinne sjen alle koade op github.

Mikrotsjinsten yn C++. Fiksje of realiteit?

En no komt it lêste stadium fan it skriuwen fan de dockerfile en docker-compose.yml. Om earlik te wêzen, dit duorre de measte tiid, en net allinnich om't ik bin in noob, om't it wie nedich om wer opbouwen fan de bibleteken eltse kear, mar fanwege de falkûlen fan conan. Bygelyks, om conan de nedige ôfhinklikens te downloaden, te ynstallearjen en te bouwen, is it net genôch om "conan install ." te downloaden, it moat ek de parameter -s compiler.libcxx=libstdc++11 trochjaan, oars jo riskearje in protte flaters te krijen by it keppeljen fan jo applikaasje. Ik bin ferskate oeren fêst sitten mei dizze flater en ik hoopje dat dit artikel oare minsken sil helpe om dit probleem yn minder tiid op te lossen.

Folgjende, nei it skriuwen fan docker-compose.yml, op advys fan myn freon, haw ik stipe tafoege koekjesfoarm en no kinne jo sels in folslein sjabloan krije foar in REST API-tsjinst yn C ++, mei in oanpaste omjouwing, en PostgreSQL ynstalleare, gewoan troch "cookiecutter" yn te fieren yn 'e konsole https://github.com/KovalevVasiliy/cpp_rest_api_template.git" En dan "docker-compose up -build".

Ik hoopje dat dit sjabloan begjinners sil helpe op har drege paad fan it ûntwikkeljen fan REST API-applikaasjes yn 'e grutte en krêftige, mar sa'n ûnhandige taal lykas C ++.
Ek ried ik tige oan om hjir te lêzen dit lidwurd. It ferklearret yn mear detail hoe't jo wurkje mei POCO en jo eigen REST API-tsjinst skriuwe.

Boarne: www.habr.com

Add a comment