Хидматҳои хурд дар C++. Фантастика ё воқеият?

Хидматҳои хурд дар C++. Фантастика ё воқеият?

Дар ин мақола ман дар бораи он сӯҳбат хоҳам кард, ки чӣ тавр ман як қолаб (кукикутер) сохтам ва барои навиштани хидмати REST API дар C++ бо истифода аз docker/docker-compose ва мудири бастаи conan муҳити эҷод кардам.

Ҳангоми ҳакатони навбатӣ, ки ман ҳамчун таҳиягари пуштибонӣ иштирок доштам, саволе ба миён омад, ки барои навиштани микросервиси навбатӣ чӣ бояд истифода кард. Ҳар он чизе, ки то имрӯз навишта шудааст, аз ҷониби ман ва ман навишта шудааст рафиқ дар Python, зеро ҳамкасби ман коршиноси ин соҳа буд ва пуштибонии касбиро таҳия кардааст, дар ҳоле ки ман умуман як таҳиягари системаҳои дохилӣ будам ва дар C++ бузург ва даҳшатнок менависам ва ман Python-ро танҳо дар донишгоҳ омӯхтам.

Ҳамин тавр, дар назди мо вазифаи навиштани хидмати сербориш қарор гирифт, ки вазифаи асосии он коркарди пешакии додаҳои ба он воридшаванда ва навиштани он ба базаи маълумот буд. Ва пас аз танаффуси дигари дуд, як дӯстам пешниҳод кард, ки ман ҳамчун як таҳиягари C++ ин хидматро бо истифода аз мутахассисон нависам. Баҳс кардан дар он аст, ки он тезтар, самараноктар хоҳад буд ва дар маҷмӯъ, ҳакамон аз он ки мо медонем, ки чӣ гуна захираҳои дастаро идора кунем, хурсанд хоҳанд шуд. Ба он ман ҷавоб додам, ки ман ҳеҷ гоҳ дар C++ чунин корҳоро накардаам ва метавонистам 20+ соати боқимондаро ба осонӣ ба ҷустуҷӯ, ҷамъоварӣ ва пайваст кардани китобхонаҳои мувофиқ сарф кунам. Оддӣ карда гӯем, ман аз ғазаб баромадам. Ин аст он чизе ки мо тасмим гирифтем ва ҳама чизро дар Python оромона анҷом додем.

Ҳоло, ҳангоми ҷудокунии маҷбурӣ, ман қарор додам, ки чӣ гуна хидматҳоро дар C++ нависед. Аввалин коре, ки бояд кард, дар бораи китобхонаи мувофиқ қарор гирифт. Интихоби ман афтод POCO, зеро он бо услуби ба объект нигаронидашуда навишта шуда буд ва инчунин бо ҳуҷҷатҳои муқаррарӣ фахр мекард. Инчунин, савол дар бораи интихоби системаи васлкунӣ ба миён омад. То ин вақт ман танҳо бо Visual Studio, IAR ва файлҳои бараҳна кор кардам. Ва ҳеҷ яке аз ин системаҳо ба ман маъқул набуд, зеро ман нақша доштам, ки тамоми хидматро дар як контейнери докер иҷро кунам. Пас аз он ман тасмим гирифтам, ки cmake ва мудири бастаи ҷолибро бифаҳмам конан. Ин менеҷери бастаҳо ба шумо имкон дод, ки ҳамаи вобастагиҳоро дар як файл сабт кунед

conanfile.txt
[талаб]poco/1.9.3
libpq/11.5

[генераторҳо] cmake

ва бо фармони оддии "conan install ." китобхонахои заруриро гузоранд. Табиист, ки ба он низ тагьирот даровардан лозим буд

CMakeLists.txt

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

Пас аз он, ман ба ҷустуҷӯи китобхона барои кор бо PostgreSQL шурӯъ кардам, зеро он китобхонае буд, ки ман бо он таҷрибаи кам доштам ва он ҳамчунин китобхонае буд, ки хидматҳои Python-и мо бо онҳо ҳамкорӣ мекарданд. Ва ту медонӣ, ки ман чӣ омӯхтам? Он дар POCO аст! Аммо Конан намедонад, ки он дар POCO аст ва намедонад, ки он чӣ гуна сохта шавад; дар анбор файли конфигуратсияи кӯҳна мавҷуд аст (ман аллакай дар бораи ин хато ба созандагони POCO навишта будам). Ин маънои онро дорад, ки шумо бояд китобхонаи дигарро ҷустуҷӯ кунед.

Ва он гоҳ интихоби ман ба китобхонаи камтар маъмул афтод libpg. Ва ман бениҳоят хушбахт будам, он аллакай дар конан буд ва ҳатто ҷамъоварӣ ва ҷамъ карда мешуд.

Қадами навбатӣ ин навиштани қолаби хадамот буд, ки метавонад дархостҳоро коркард кунад.
Мо бояд синфи TemplateServerApp-и худро аз Poco::Util::ServerApplication мерос гирем ва усули асосиро бекор кунем.

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

Дар усули асосӣ мо бояд параметрҳоро муқаррар кунем: порт, шумораи риштаҳо ва андозаи навбат. Ва муҳимтар аз ҳама, шумо бояд коркардкунандаро барои дархостҳои воридотӣ муайян кунед. Ин кор бо рохи барпо намудани завод ба амал меояд

TemplateRequestHandlerFactory

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

Дар ҳолати ман, он ҳар дафъа як коркардкунандаро эҷод мекунад - TemplateServerAppHandler. Дар ин ҷо мо метавонем мантиқи тиҷорати худро ҷойгир кунем.

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 эҷод кардам. Барои иҷрои SQL оддӣ, ба монанди сохтани ҷадвал, як усул вуҷуд дорад ExecuteSQL(). Барои пурсишҳои мураккабтар ё ҷустуҷӯи маълумот, шумо бояд пайвастшавӣ тавассути GetConnection() ва API-и libpg -ро истифода баред. (Шояд баъдтар ин беадолатиро ислох кунам).

Махзани

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

Ҳама параметрҳо барои пайвастшавӣ ба пойгоҳи додаҳо аз муҳити зист гирифта шудаанд, бинобар ин шумо инчунин бояд файли .env -ро эҷод ва танзим кунед

.env

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

Шумо метавонед ҳамаи кодҳоро дар github.

Хидматҳои хурд дар C++. Фантастика ё воқеият?

Ва ҳоло марҳилаи ниҳоии навиштани dockerfile ва docker-compose.yml фаро мерасад. Рости гап, ин бештари вақтро талаб мекард ва на танҳо аз он сабаб, ки ман нооб ҳастам, зеро ҳар дафъа китобхонаҳоро аз нав сохтан лозим буд, балки аз сабаби домҳои Конан. Масалан, барои боргирӣ, насб ва сохтани вобастагии зарурии конан, барои зеркашии "conan install ." кифоя нест, он инчунин бояд параметри -s compiler.libcxx=libstdc++11-ро гузаронад, вагарна шумо хавфи ба даст овардани як қатор хатогиҳо дар марҳилаи пайваст кардани дархости шумо мешавед. Ман чанд соат боз бо ин иштибоҳ мондам ва умедворам, ки ин мақола ба дигарон дар ҳалли ин мушкилот дар муддати кӯтоҳ кӯмак хоҳад кард.

Баъдан, пас аз навиштани docker-compose.yml, бо маслиҳати дӯстам, ман дастгирӣ илова кардам кукибур ва акнун шумо метавонед ба худ як қолаби мукаммал барои хидмати REST API дар C++, бо муҳити фармоишӣ ва насби PostgreSQL, танҳо тавассути ворид кардани "cookiecutter" ба консол дастрас кунед. https://github.com/KovalevVasiliy/cpp_rest_api_template.git" Ва он гоҳ "докер-ташкил -сохт".

Умедворам, ки ин қолаб ба шурӯъкунандагон дар роҳи душвори таҳияи барномаҳои REST API дар бузург ва тавоно, вале чунин забони нофаҳмо ба мисли C++ кӯмак хоҳад кард.
Инчунин, ман тавсия медиҳам, ки дар ин ҷо хонед ин мақола. Он ба таври муфассал шарҳ медиҳад, ки чӣ гуна бо POCO кор кардан ва хидмати REST API-и худро нависед.

Манбаъ: will.com

Илова Эзоҳ