C++ тилиндеги микросервистер. Ойдон чыгарылганбы же чындыкпы?

C++ тилиндеги микросервистер. Ойдон чыгарылганбы же чындыкпы?

Бул макалада мен шаблонду (cookiecutter) кантип түзгөнүм жана docker/docker-compose жана conan пакет менеджери аркылуу C++ тилинде REST API кызматын жазуу үчүн чөйрөнү кантип түзгөнүм жөнүндө сүйлөшөм.

Мен бэкендди иштеп чыгуучу катары катышкан кийинки хакатондо кийинки микросервисти жазуу үчүн эмнени колдонуу керек деген суроо пайда болду. Буга чейин жазылгандардын бардыгын мен жана мен жазганбыз жолдош Pythonдо, менин кесиптешим бул тармактын адиси жана профессионалдуу түрдө иштелип чыккан бэкенддер болгондуктан, мен жалпысынан орнотулган системаларды иштеп чыгуучумун жана улуу жана коркунучтуу C++ тилинде жазганмын жана мен Pythonду университетте жаңы эле үйрөнгөм.

Ошентип, биздин алдыбызда жогорку жүктөмдүү кызматты жазуу милдети турду, анын негизги милдети ага келген маалыматтарды алдын ала иштеп чыгуу жана аны маалымат базасына жазуу. Дагы бир түтүн тыныгуусунан кийин, досум мага C++ иштеп чыгуучусу катары бул кызматты профессионалдар менен жазууну сунуштады. Бул тезирээк, жемиштүү болот жана жалпысынан, калыстар тобу биз команданын ресурстарын кантип башкарууну билгенибизге ыраазы болушат. Буга мен C++ тилинде мындай нерселерди эч качан жасаган эмесмин жана калган 20+ саатты ылайыктуу китепканаларды издөөгө, компиляциялоого жана байланыштырууга оңой эле жумшайм деп жооп бердим. Жөнөкөй сөз менен айтканда, мен кууп чыктым. Бул биз чечтик жана тынч Python баарын бүтүрдү.

Эми, мажбурлап өзүнчө обочолонуу учурунда мен C++ тилинде кызматтарды кантип жазууну чечтим. Биринчи кезекте ылайыктуу китепкананы тандоо керек болчу. Менин тандоом туура келди КТРК, анткени ал объектке багытталган стилде жазылган жана ошондой эле кадимки документтер менен мактанган. Ошондой эле, суроо монтаждоо системасын тандоо жөнүндө пайда болгон. Ушул убакка чейин мен Visual Studio, IAR жана жылаңач макфилдер менен гана иштедим. Жана бул системалардын бири дагы мага жаккан жок, анткени мен бүт кызматты докер контейнеринде иштетүүнү пландаштыргам. Анан мен cmake жана кызыктуу пакет менеджерин табууга аракет кылууну чечтим Конан. Бул пакет менеджери бардык көз карандылыктарды бир файлда каттоого мүмкүндүк берди

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

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

жана жөнөкөй буйрук менен "conan орнотуу ." зарыл китепканаларды орнотуу. Албетте, өзгөртүү киргизүүгө да туура келди

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++ тилиндеги REST API кызматы үчүн толук кандуу шаблонду ала аласыз, ыңгайлаштырылган чөйрөсү жана PostgreSQL орнотулган. https://github.com/KovalevVasiliy/cpp_rest_api_template.git" Анан "докер-композит - куруу".

Бул шаблон жаңы баштагандарга REST API тиркемелерин улуу жана күчтүү, бирок C++ сыяктуу олдоксон тилде иштеп чыгуунун татаал жолунда жардам берет деп үмүттөнөм.
Ошондой эле, мен бул жерден окууну сунуштайм бул макала. Бул POCO менен кантип иштөөнү жана өз REST API кызматыңызды кантип жазууну кененирээк түшүндүрөт.

Source: www.habr.com

Комментарий кошуу