C++ ۾ مائڪرو سروسز. افسانو يا حقيقت؟

C++ ۾ مائڪرو سروسز. افسانو يا حقيقت؟

هن آرٽيڪل ۾ آئون انهي بابت ڳالهائيندس ته مون هڪ ٽيمپليٽ (cookiecutter) ڪيئن ٺاهيو ۽ سي ++ ۾ هڪ REST API سروس لکڻ لاءِ ماحول قائم ڪيو docker/docker-compose ۽ conan پيڪيج مئنيجر استعمال ڪندي.

ايندڙ هيڪاٿون دوران، جنهن ۾ مون هڪ پس منظر ڊولپر جي حيثيت ۾ حصو ورتو، سوال اڀريو ته ايندڙ مائڪرو سروس لکڻ لاءِ ڇا استعمال ڪجي. هن وقت تائين جيڪو ڪجهه لکيو ويو آهي اهو سڀ ڪجهه منهنجي ۽ منهنجي طرفان لکيو ويو آهي ڪامريڊ پٿون ۾، ڇاڪاڻ ته منهنجو ساٿي هن فيلڊ ۾ ماهر هو ۽ پيشه ور طور تي ترقي يافته پس منظر هئا، جڏهن ته آئون عام طور تي هڪ ايمبيڊڊ سسٽم ڊولپر هو ۽ عظيم ۽ خوفناڪ C++ ۾ لکندو هو، ۽ مون صرف يونيورسٽي ۾ پٿون سکيو هو.

تنهن ڪري، اسان کي هڪ اعلي-لوڊ سروس لکڻ جي ڪم سان منهن ڏيڻو پيو، جنهن جو بنيادي ڪم اهو هو ته ڊيٽا کي اڳڀرائي ڪرڻ ۽ ان کي ڊيٽابيس ۾ لکڻ. ۽ هڪ ٻي تماڪ جي وقفي کان پوءِ، هڪ دوست صلاح ڏني ته مان، هڪ C++ ڊولپر جي حيثيت سان، هن خدمت کي استعمال ڪندي لکان. دليل ڏيڻ اهو آهي ته اهو تيز، وڌيڪ پيداوار وارو، ۽ عام طور تي، جوري خوش ٿيندو ته اسان ڪيئن ڄاڻون ٿا ته ٽيم جي وسيلن کي ڪيئن منظم ڪجي. جنهن تي مون جواب ڏنو ته مون اهڙيون شيون ڪڏهن به C++ ۾ نه ڪيون آهن ۽ باقي 20+ ڪلاڪ آسانيءَ سان مناسب لائبريرين کي ڳولڻ، مرتب ڪرڻ ۽ ڳنڍڻ لاءِ وقف ڪري سگهندس. آسانيءَ سان، مون ڪڪڙ ڪڍي ڇڏيو. اھو اھو آھي جيڪو اسان فيصلو ڪيو ۽ آرام سان پٿون ۾ سڀ ڪجھ مڪمل ڪيو.

ھاڻي، زبردستي خود اڪيلائي دوران، مون اھو معلوم ڪرڻ جو فيصلو ڪيو ته C++ ۾ خدمتون ڪيئن لکجي. ڪرڻ جو پهريون ڪم هڪ مناسب لائبريري تي فيصلو ڪيو ويو. منهنجي پسند تي اچي ويو POCO, ڇاڪاڻ ته اهو هڪ اعتراض تي مبني انداز ۾ لکيو ويو آهي ۽ پڻ عام دستاويزن تي فخر ڪيو ويو آهي. ان کان علاوه، سوال هڪ اسيمبلي جي نظام کي چونڊڻ بابت پيدا ٿيو. هن وقت تائين مون صرف Visual Studio، IAR ۽ bare makefiles سان ڪم ڪيو آهي. ۽ انهن سسٽم مان ڪنهن به مون کي اپيل نه ڪئي، ڇو ته مون سڄي خدمت کي ڊاکر ڪنٽينر ۾ هلائڻ جو منصوبو ڪيو. ان کان پوء مون کي معلوم ڪرڻ جي ڪوشش ڪرڻ جو فيصلو ڪيو cmake ۽ هڪ دلچسپ پيڪيج مينيجر ڪنن. هي پيڪيج مينيجر توهان کي هڪ فائل ۾ سڀني انحصار کي رجسٽر ڪرڻ جي اجازت ڏني

conanfile.txt
پوڪو/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})

ان کان پوء، مون پوسٽ گري ايس ايس ايل سان ڪم ڪرڻ لاء هڪ لائبريري ڳولڻ شروع ڪيو، ڇاڪاڻ ته اها هڪ هئي جنهن سان مون کي ڪم ڪرڻ جو ٿورو تجربو هو، ۽ اهو پڻ هو ته اسان جي پٿون خدمتن سان رابطو ڪيو. ۽ توهان کي خبر آهي ته مون ڇا سکيو؟ اهو POCO ۾ آهي! پر ڪنن کي خبر ناهي ته اهو POCO ۾ آهي ۽ نه ڄاڻندو آهي ته ان کي ڪيئن ٺاهيو؛ مخزن ۾ هڪ پراڻي ترتيب واري فائيل آهي (مون اڳ ۾ ئي POCO جي تخليق ڪندڙن کي هن غلطي بابت لکيو آهي). ان جو مطلب آهي ته توهان کي ٻي لائبريري ڳولڻو پوندو.

۽ پوءِ منهنجي پسند هڪ گهٽ مشهور لائبريري تي ٿي libpg. ۽ مان ناقابل يقين حد تائين خوش قسمت هوس، اهو اڳ ۾ ئي ڪانن ۾ هو ۽ اڃا به گڏ ۽ گڏ ڪيو پيو وڃي.

ايندڙ قدم هڪ خدمت ٽيمپليٽ لکڻ هو جيڪو درخواستن تي عمل ڪري سگهي ٿو.
اسان کي پوڪو::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(). وڌيڪ پيچيده سوالن يا ڊيٽا حاصل ڪرڻ لاء، توهان کي حاصل ڪرڻو پوندو ذريعي ڪنيڪشن ڪنيڪشن حاصل ڪريو () ۽ 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

توھان سڀ ڪوڊ ڏسي سگھوٿا گيتب

C++ ۾ مائڪرو سروسز. افسانو يا حقيقت؟

۽ هاڻي اچي ٿو آخري مرحلو لکڻ جو dockerfile ۽ docker-compose.yml. سچ پڇو، اهو گهڻو وقت وٺندو آهي، ۽ نه صرف ان ڪري جو مان هڪ نوب آهيان، ڇاڪاڻ ته اهو ضروري هو ته لائبريرين کي هر وقت ٻيهر تعمير ڪيو وڃي، پر ڪنن جي نقصانن جي ڪري. مثال طور، ڪانن کي ڊائون لوڊ ڪرڻ، انسٽال ڪرڻ ۽ ضروري انحصار ٺاهڻ لاءِ، ان لاءِ ”ڪونان انسٽال“ ڊائون لوڊ ڪرڻ ڪافي ناهي، ان کي پڻ پاس ڪرڻ جي ضرورت آهي -s compiler.libcxx=libstdc++11 پيٽرول، ٻي صورت ۾. توهان کي توهان جي ايپليڪيشن کي ڳنڍڻ واري مرحلي ۾ غلطين جو هڪ گروپ حاصل ڪرڻ جو خطرو آهي. مان ڪيترن ئي ڪلاڪن کان هن غلطي سان بيٺو آهيان ۽ اميد اٿم ته هي آرٽيڪل ٻين ماڻهن کي گهٽ وقت ۾ هن مسئلي کي حل ڪرڻ ۾ مدد ڪندو.

اڳيون، docker-compose.yml لکڻ کان پوء، منهنجي دوست جي صلاح تي، مون سپورٽ شامل ڪيو ڪوڪيڪٽر ۽ ھاڻي توھان حاصل ڪري سگھوٿا ھڪ مڪمل ٽيمپليٽ C++ ۾ REST API سروس لاءِ، ڪسٽمائيز ماحول سان، ۽ PostgreSQL انسٽال ٿيل آھي، بس ڪنسول ۾ ”cookiecutter“ داخل ڪرڻ سان https://github.com/KovalevVasiliy/cpp_rest_api_template.git" ۽ پوءِ ”ڊاڪر-ڪپوز اپ -بلڊ“.

مون کي اميد آهي ته هي ٽيمپليٽ نئين سکندڙن کي وڏي ۽ طاقتور ۾ REST API ايپليڪيشنن کي ترقي ڪرڻ جي مشڪل رستي تي مدد ڪندي، پر اهڙي بيڪار ٻولي جهڙوڪ C++.
انهي سان گڏ، آئون هتي پڙهڻ جي سفارش ڪريان ٿو هي مضمون. اهو وڌيڪ تفصيل سان بيان ڪري ٿو ته POCO سان ڪيئن ڪم ڪجي ۽ پنهنجو REST API سروس لکجي.

جو ذريعو: www.habr.com

تبصرو شامل ڪريو