Дар ин мақола ман дар бораи он сӯҳбат хоҳам кард, ки чӣ тавр ман як қолаб (кукикутер) сохтам ва барои навиштани хидмати REST API дар C++ бо истифода аз docker/docker-compose ва мудири бастаи conan муҳити эҷод кардам.
Ҳангоми ҳакатони навбатӣ, ки ман ҳамчун таҳиягари пуштибонӣ иштирок доштам, саволе ба миён омад, ки барои навиштани микросервиси навбатӣ чӣ бояд истифода кард. Ҳар он чизе, ки то имрӯз навишта шудааст, аз ҷониби ман ва ман навишта шудааст
Ҳамин тавр, дар назди мо вазифаи навиштани хидмати сербориш қарор гирифт, ки вазифаи асосии он коркарди пешакии додаҳои ба он воридшаванда ва навиштани он ба базаи маълумот буд. Ва пас аз танаффуси дигари дуд, як дӯстам пешниҳод кард, ки ман ҳамчун як таҳиягари C++ ин хидматро бо истифода аз мутахассисон нависам. Баҳс кардан дар он аст, ки он тезтар, самараноктар хоҳад буд ва дар маҷмӯъ, ҳакамон аз он ки мо медонем, ки чӣ гуна захираҳои дастаро идора кунем, хурсанд хоҳанд шуд. Ба он ман ҷавоб додам, ки ман ҳеҷ гоҳ дар C++ чунин корҳоро накардаам ва метавонистам 20+ соати боқимондаро ба осонӣ ба ҷустуҷӯ, ҷамъоварӣ ва пайваст кардани китобхонаҳои мувофиқ сарф кунам. Оддӣ карда гӯем, ман аз ғазаб баромадам. Ин аст он чизе ки мо тасмим гирифтем ва ҳама чизро дар Python оромона анҷом додем.
Ҳоло, ҳангоми ҷудокунии маҷбурӣ, ман қарор додам, ки чӣ гуна хидматҳоро дар C++ нависед. Аввалин коре, ки бояд кард, дар бораи китобхонаи мувофиқ қарор гирифт. Интихоби ман афтод
conanfile.txt
[талаб]poco/1.9.3
libpq/11.5
ва бо фармони оддии "conan install ." китобхонахои заруриро гузоранд. Табиист, ки ба он низ тагьирот даровардан лозим буд
CMakeLists.txt
include(build/conanbuildinfo.cmake)
conan_basic_setup()
target_link_libraries(<target_name> ${CONAN_LIBS})
Пас аз он, ман ба ҷустуҷӯи китобхона барои кор бо PostgreSQL шурӯъ кардам, зеро он китобхонае буд, ки ман бо он таҷрибаи кам доштам ва он ҳамчунин китобхонае буд, ки хидматҳои Python-и мо бо онҳо ҳамкорӣ мекарданд. Ва ту медонӣ, ки ман чӣ омӯхтам? Он дар POCO аст! Аммо Конан намедонад, ки он дар POCO аст ва намедонад, ки он чӣ гуна сохта шавад; дар анбор файли конфигуратсияи кӯҳна мавҷуд аст (ман аллакай дар бораи ин хато ба созандагони POCO навишта будам). Ин маънои онро дорад, ки шумо бояд китобхонаи дигарро ҷустуҷӯ кунед.
Ва он гоҳ интихоби ман ба китобхонаи камтар маъмул афтод
Қадами навбатӣ ин навиштани қолаби хадамот буд, ки метавонад дархостҳоро коркард кунад.
Мо бояд синфи 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() ва API-и libpg -ро истифода баред. (Шояд баъдтар ин беадолатиро ислох кунам).
Махзани
#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
Шумо метавонед ҳамаи кодҳоро дар
Ва ҳоло марҳилаи ниҳоии навиштани dockerfile ва docker-compose.yml фаро мерасад. Рости гап, ин бештари вақтро талаб мекард ва на танҳо аз он сабаб, ки ман нооб ҳастам, зеро ҳар дафъа китобхонаҳоро аз нав сохтан лозим буд, балки аз сабаби домҳои Конан. Масалан, барои боргирӣ, насб ва сохтани вобастагии зарурии конан, барои зеркашии "conan install ." кифоя нест, он инчунин бояд параметри -s compiler.libcxx=libstdc++11-ро гузаронад, вагарна шумо хавфи ба даст овардани як қатор хатогиҳо дар марҳилаи пайваст кардани дархости шумо мешавед. Ман чанд соат боз бо ин иштибоҳ мондам ва умедворам, ки ин мақола ба дигарон дар ҳалли ин мушкилот дар муддати кӯтоҳ кӯмак хоҳад кард.
Баъдан, пас аз навиштани docker-compose.yml, бо маслиҳати дӯстам, ман дастгирӣ илова кардам
Умедворам, ки ин қолаб ба шурӯъкунандагон дар роҳи душвори таҳияи барномаҳои REST API дар бузург ва тавоно, вале чунин забони нофаҳмо ба мисли C++ кӯмак хоҳад кард.
Инчунин, ман тавсия медиҳам, ки дар ин ҷо хонед
Манбаъ: will.com