C++ тіліндегі микросервистер. Фантастика немесе шындық?

C++ тіліндегі микросервистер. Фантастика немесе шындық?

Бұл мақалада мен шаблонды (cookiecutter) қалай жасағаным және docker/docker-compose және conan пакет менеджері арқылы C++ тілінде REST API қызметін жазу үшін ортаны қалай орнатқаным туралы айтатын боламын.

Мен бэкенд әзірлеушісі ретінде қатысқан келесі хакатон кезінде келесі микросервисті жазу үшін нені пайдалану керек деген сұрақ туындады. Осы уақытқа дейін жазылғанның барлығын мен және мен жаздым жолдас 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() және libpg API пайдаланыңыз. (Бұл әділетсіздікті кейін түзететін шығармын).

дерекқор

#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 жазғаннан кейін, досымның кеңесімен мен қолдауды қостым печеньеші және енді консольге жай ғана «cookiecutter» енгізу арқылы C++ тіліндегі, теңшелген ортасы және PostgreSQL орнатылған REST API қызметі үшін толыққанды үлгі алуға болады. https://github.com/KovalevVasiliy/cpp_rest_api_template.git" Содан кейін «докер-құрастыру — құрастыру».

Бұл үлгі жаңадан бастағандарға керемет және қуатты, бірақ C++ сияқты ебедейсіз тілде REST API қосымшаларын жасаудың қиын жолында көмектеседі деп үміттенемін.
Сонымен қатар, мен мұнда оқуға кеңес беремін бұл мақала. Ол POCO-мен жұмыс істеу және өзіңіздің REST API қызметін жазу жолын толығырақ түсіндіреді.

Ақпарат көзі: www.habr.com

пікір қалдыру