C++ හි ක්ෂුද්‍ර සේවා. ප්‍රබන්ධ හෝ යථාර්ථය?

C++ හි ක්ෂුද්‍ර සේවා. ප්‍රබන්ධ හෝ යථාර්ථය?

මෙම ලිපියෙන් මම ඩොකර්/ඩොකර්-කොම්පෝස් සහ කොනන් පැකේජ කළමණාකරු භාවිතා කර C++ හි REST API සේවාවක් ලිවීම සඳහා සැකිල්ලක් (cookiecutter) නිර්මාණය කර පරිසරයක් සකසන ආකාරය ගැන කතා කරමි.

පසුපෙළ සංවර්ධකයෙකු ලෙස මා සහභාගී වූ ඊළඟ hackathon අතරතුර, මීළඟ microservice ලිවීමට භාවිතා කරන්නේ කුමක් ද යන ප්‍රශ්නය මතු විය. මෙතෙක් ලියැවුණු හැම දෙයක්ම මම සහ මගේ අතින් ලියැවුණු ඒවා සහෝදරයා Python හි, මගේ සගයා මෙම ක්ෂේත්‍රයේ ප්‍රවීණයෙකු වූ අතර වෘත්තීයමය වශයෙන් දියුණු පසුබිම් ඇති බැවින්, මම සාමාන්‍යයෙන් කාවැද්දූ පද්ධති සංවර්ධකයෙකු වූ අතර විශිෂ්ට හා භයානක C++ හි ලිවීය, සහ මම විශ්ව විද්‍යාලයේදී පයිතන් ඉගෙන ගත්තෙමි.

ඉතින්, අපට අධි බර සේවාවක් ලිවීමේ කාර්යයට මුහුණ දීමට සිදු විය, එහි ප්‍රධාන කාර්යය වූයේ එයට එන දත්ත පෙර සැකසුම් කර දත්ත ගබඩාවට ලිවීමයි. තවත් දුම් විවේකයකින් පසු, මිතුරෙකු යෝජනා කළේ මම, C++ සංවර්ධකයෙකු ලෙස, වාසි භාවිතා කරමින් මෙම සේවාව ලිවීමට ය. මෙය තර්ක කරන්නේ එය වේගවත්, වඩා ඵලදායී වනු ඇති අතර, සාමාන්යයෙන්, කණ්ඩායමේ සම්පත් කළමනාකරණය කරන්නේ කෙසේදැයි අප දන්නා ආකාරය ගැන ජූරි සභාව සතුටු වනු ඇත. එයට මම පිළිතුරු දුන්නේ මම කිසි විටෙකත් C++ හි එවැනි දේ කර නොමැති බවත්, සුදුසු පුස්තකාල සෙවීමට, සම්පාදනය කිරීමට සහ සම්බන්ධ කිරීමට ඉතිරි පැය 20+ පහසුවෙන් කැප කළ හැකි බවත්ය. සරලව කිවහොත්, මම කුකුල් කළෙමි. අපි තීරණය කර සන්සුන්ව පයිතන් හි සියල්ල සම්පූර්ණ කළේ එයයි.

දැන්, බලහත්කාරයෙන් ස්වයං හුදකලා වීම අතරතුර, මම C++ හි සේවාවන් ලියන්නේ කෙසේදැයි සොයා ගැනීමට තීරණය කළෙමි. මුලින්ම කළ යුත්තේ සුදුසු පුස්තකාලයක් තීරණය කිරීමයි. මගේ තේරීම වැටුණා POCO, එය වස්තු-නැඹුරු ශෛලියකින් ලියා ඇති නිසා සහ සාමාන්‍ය ලියකියවිලි ගැනද පුරසාරම් දොඩයි. එසේම, එකලස් කිරීමේ පද්ධතියක් තෝරා ගැනීම පිළිබඳ ප්රශ්නය මතු විය. මම මේ දක්වා වැඩ කර ඇත්තේ විෂුවල් ස්ටුඩියෝ, අයිඒආර් සහ බෙයා මේක්ෆයිල්ස් සමඟ පමණි. මම සම්පූර්ණ සේවාවම ඩොකර් කන්ටේනරයක ක්‍රියාත්මක කිරීමට සැලසුම් කළ නිසා මෙම පද්ධති කිසිවක් මා සිත් ගත්තේ නැත. එවිට මම 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. මම ඇදහිය නොහැකි තරම් වාසනාවන්තයි, එය දැනටමත් කොනන් වල තිබූ අතර එකලස් කර එකලස් කර ඇත.

ඊළඟ පියවර වූයේ ඉල්ලීම් සැකසීමට හැකි සේවා ආකෘතියක් ලිවීමයි.
අපි Poco::Util::ServerApplication වෙතින් අපගේ TemplateServerApp පන්තිය උරුම කර ප්‍රධාන ක්‍රමය අභිබවා යා යුතුය.

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 සඳහා අවශ්‍ය පරායත්තයන් බාගත කිරීම, ස්ථාපනය කිරීම සහ ගොඩ නැගීම සඳහා, එය “conan install .” බාගත කිරීම ප්‍රමාණවත් නොවේ, එය -s compiler.libcxx=libstdc++11 පරාමිතිය පසු කිරීමටද අවශ්‍ය වේ. ඔබගේ යෙදුම සම්බන්ධ කිරීමේ අදියරේදී ඔබට දෝෂ රාශියක් ඇතිවීමේ අවදානමක් ඇත. මම පැය කිහිපයක් තිස්සේ මෙම දෝෂය සමඟ සිරවී සිටි අතර මෙම ලිපිය අඩු කාලයක් තුළ මෙම ගැටළුව විසඳීමට අනෙක් අයට උපකාරී වනු ඇතැයි මම බලාපොරොත්තු වෙමි.

ඊලඟට docker-compose.yml ලිව්වට පස්සේ මගේ යාළුවාගේ උපදෙස් මත මම සහයෝගයක් එකතු කළා කුකීකට්ටර් දැන් ඔබට C++ හි REST API සේවාවක් සඳහා අභිරුචිකරණය කළ පරිසරයක් සහ PostgreSQL ස්ථාපනය කර ඇති අතර, හුදෙක් කොන්සෝලයට “කුකීකට්ටරය” ඇතුළත් කිරීමෙන් ඔබටම ලබා ගත හැක. https://github.com/KovalevVasiliy/cpp_rest_api_template.git" ඉන්පසු "ඩොකර්-රචනය කරන්න - ගොඩනඟන්න".

මෙම අච්චුව ආධුනිකයන්ට REST API යෙදුම් විශිෂ්ට සහ බලවත්, නමුත් C++ වැනි අවුල් සහගත භාෂාවකින් සංවර්ධනය කිරීමේ දුෂ්කර මාවතට උපකාර කරනු ඇතැයි මම බලාපොරොත්තු වෙමි.
එසේම, මම මෙහි කියවීමට තරයේ නිර්දේශ කරමි මේ ලිපිය. එය POCO සමඟ වැඩ කරන්නේ කෙසේද සහ ඔබේම REST API සේවාවක් ලියන්නේ කෙසේද යන්න වඩාත් විස්තරාත්මකව විස්තර කරයි.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න