C++ میں مائیکرو سروسز۔ افسانہ یا حقیقت؟

C++ میں مائیکرو سروسز۔ افسانہ یا حقیقت؟

اس آرٹیکل میں میں اس بارے میں بات کروں گا کہ میں نے ٹیمپلیٹ (cookiecutter) کیسے بنایا اور docker/docker-compose اور conan پیکیج مینیجر کا استعمال کرتے ہوئے C++ میں REST API سروس لکھنے کے لیے ماحول قائم کیا۔

اگلے ہیکاتھون کے دوران، جس میں میں نے بیک اینڈ ڈویلپر کے طور پر حصہ لیا، سوال پیدا ہوا کہ اگلی مائیکرو سروس لکھنے کے لیے کیا استعمال کیا جائے۔ اب تک جو کچھ لکھا گیا ہے وہ سب میں نے اور میرا لکھا ہے۔ کامریڈ Python میں، چونکہ میرا ساتھی اس شعبے کا ماہر تھا اور پیشہ ورانہ طور پر بیک اینڈ تیار کرتا تھا، جب کہ میں عام طور پر ایک ایمبیڈڈ سسٹم ڈویلپر تھا اور میں نے زبردست اور خوفناک C++ میں لکھا تھا، اور میں نے ابھی یونیورسٹی میں Python سیکھا ہے۔

لہذا، ہمیں ایک ہائی لوڈ سروس لکھنے کے کام کا سامنا کرنا پڑا، جس کا بنیادی کام اس پر آنے والے ڈیٹا کو پہلے سے پروسیس کرنا اور اسے ڈیٹا بیس میں لکھنا تھا۔ اور ایک اور دھوئیں کے وقفے کے بعد، ایک دوست نے مشورہ دیا کہ میں، بطور C++ ڈویلپر، پیشہ کا استعمال کرتے ہوئے اس سروس کو لکھوں۔ اس کا استدلال یہ ہے کہ یہ تیز تر، زیادہ نتیجہ خیز ہوگا، اور عام طور پر، جیوری اس بات سے خوش ہوگی کہ ہم ٹیم کے وسائل کو کس طرح منظم کرنا جانتے ہیں۔ جس پر میں نے جواب دیا کہ میں نے C++ میں ایسی چیزیں کبھی نہیں کیں اور بقیہ 20+ گھنٹے آسانی سے موزوں لائبریریوں کو تلاش کرنے، مرتب کرنے اور لنک کرنے کے لیے وقف کر سکتا ہوں۔ سیدھے الفاظ میں ، میں نے چکن آؤٹ کیا۔ یہ وہی ہے جس پر ہم نے فیصلہ کیا اور سکون سے Python میں سب کچھ مکمل کیا۔

اب، جبری خود تنہائی کے دوران، میں نے یہ جاننے کا فیصلہ کیا کہ C++ میں خدمات کیسے لکھی جائیں۔ سب سے پہلے ایک مناسب لائبریری کا فیصلہ کرنا تھا۔ میرا انتخاب گر گیا۔ میں Poco، چونکہ یہ آبجیکٹ پر مبنی انداز میں لکھا گیا تھا اور عام دستاویزات پر بھی فخر کیا گیا تھا۔ اس کے علاوہ اسمبلی کے نظام کے انتخاب کے بارے میں بھی سوال پیدا ہوا۔ اس وقت تک میں نے صرف ویژول اسٹوڈیو، IAR اور ننگی میک فائلز کے ساتھ کام کیا ہے۔ اور ان میں سے کسی بھی سسٹم نے مجھ سے اپیل نہیں کی، کیونکہ میں نے پوری سروس کو ڈوکر کنٹینر میں چلانے کا منصوبہ بنایا تھا۔ پھر میں نے 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})

اس کے بعد، میں نے PostgreSQL کے ساتھ کام کرنے کے لیے ایک لائبریری کی تلاش شروع کی، کیونکہ یہ وہ تھی جس کے ساتھ مجھے کام کرنے کا بہت کم تجربہ تھا، اور یہ وہ تھی جس کے ساتھ ہماری Python سروسز نے بات چیت کی۔ اور کیا آپ جانتے ہیں کہ میں نے کیا سیکھا؟ یہ POCO میں ہے! لیکن کونن نہیں جانتا کہ یہ POCO میں ہے اور اسے نہیں معلوم کہ اسے کیسے بنایا جائے؛ ذخیرے میں ایک پرانی کنفیگریشن فائل ہے (میں اس غلطی کے بارے میں POCO کے تخلیق کاروں کو پہلے ہی لکھ چکا ہوں)۔ اس کا مطلب ہے کہ آپ کو دوسری لائبریری تلاش کرنی ہوگی۔

اور پھر میری پسند ایک کم مقبول لائبریری پر پڑی۔ libpg. اور میں ناقابل یقین حد تک خوش قسمت تھا، یہ پہلے ہی کانن میں تھا اور یہاں تک کہ اسمبل اور اسمبل کیا جا رہا تھا۔

اگلا مرحلہ ایک سروس ٹیمپلیٹ لکھنا تھا جو درخواستوں پر کارروائی کر سکے۔
ہمیں 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 کے ساتھ کام کرنے کے لیے ایک کلاس ٹیمپلیٹ بھی بنایا ہے۔ سادہ ایس کیو ایل کو انجام دینے کے لیے، جیسا کہ ٹیبل بنانا، ایک طریقہ ہے۔ 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 لکھنے کا آخری مرحلہ آتا ہے۔ سچ پوچھیں تو، اس میں زیادہ تر وقت لگا، اور نہ صرف اس لیے کہ میں ایک نوب ہوں، کیونکہ لائبریریوں کو ہر بار دوبارہ بنانا ضروری تھا، بلکہ کانن کے نقصانات کی وجہ سے۔ مثال کے طور پر، conan کے لیے ضروری انحصار کو ڈاؤن لوڈ، انسٹال اور بنانے کے لیے، اس کے لیے "conan install" ڈاؤن لوڈ کرنا کافی نہیں ہے، اسے -s compiler.libcxx=libstdc++11 پیرامیٹر کو بھی پاس کرنا ہوگا، بصورت دیگر آپ کو اپنی درخواست کو لنک کرنے کے مرحلے پر غلطیوں کا ایک گروپ ہونے کا خطرہ ہے۔ میں کئی گھنٹوں سے اس خرابی میں پھنسا ہوا ہوں اور مجھے امید ہے کہ یہ مضمون کم وقت میں اس مسئلے کو حل کرنے میں دوسرے لوگوں کی مدد کرے گا۔

اس کے بعد، docker-compose.yml لکھنے کے بعد، اپنے دوست کے مشورے پر، میں نے تعاون شامل کیا۔ کوکی کٹر اور اب آپ اپنے آپ کو C++ میں REST API سروس کے لیے ایک مکمل ٹیمپلیٹ حاصل کر سکتے ہیں، اپنی مرضی کے مطابق ماحول کے ساتھ، اور PostgreSQL انسٹال کر سکتے ہیں، بس کنسول میں "cookiecutter" داخل کر کے۔ https://github.com/KovalevVasiliy/cpp_rest_api_template.git" اور پھر "docker-compose up —build"۔

مجھے امید ہے کہ یہ ٹیمپلیٹ شروع کرنے والوں کو REST API ایپلیکیشنز کو عظیم اور طاقتور، لیکن C++ جیسی اناڑی زبان میں تیار کرنے کے مشکل راستے پر مدد کرے گا۔
اس کے علاوہ، میں یہاں پڑھنے کی انتہائی سفارش کرتا ہوں۔ یہ مضمون یہ مزید تفصیل سے بتاتا ہے کہ POCO کے ساتھ کیسے کام کرنا ہے اور اپنی REST API سروس لکھنا ہے۔

ماخذ: www.habr.com

نیا تبصرہ شامل کریں