Бұл мақалада мен шаблонды (cookiecutter) қалай жасағаным және docker/docker-compose және conan пакет менеджері арқылы C++ тілінде REST API қызметін жазу үшін ортаны қалай орнатқаным туралы айтатын боламын.
Мен бэкенд әзірлеушісі ретінде қатысқан келесі хакатон кезінде келесі микросервисті жазу үшін нені пайдалану керек деген сұрақ туындады. Осы уақытқа дейін жазылғанның барлығын мен және мен жаздым
Сонымен, біздің алдымызда үлкен жүктемелі қызметті жазу міндеті тұрды, оның негізгі міндеті оған келетін деректерді алдын ала өңдеу және оны дерекқорға жазу болды. Тағы бір түтін үзілістен кейін досым маған 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() және 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
Барлық кодты мына жерден көре аласыз
Енді dockerfile және docker-compose.yml файлдарын жазудың соңғы кезеңі келеді. Шынымды айтсам, бұл көп уақытты алды, бұл мен ұқыпты болғандықтан ғана емес, кітапханаларды әр уақытта қайта құру қажет болғандықтан, сонымен қатар Конанның тұзақтарына байланысты. Мысалы, конанға қажетті тәуелділіктерді жүктеп алу, орнату және құру үшін «conan install .» жүктеп алу жеткіліксіз, ол сонымен қатар -s compiler.libcxx=libstdc++11 параметрін беруі керек, әйтпесе қолданбаңызды байланыстыру кезеңінде көптеген қателерді алу қаупі бар. Мен бұл қатемен бірнеше сағат бойы тұрып қалдым және бұл мақала басқа адамдарға бұл мәселені қысқа мерзімде шешуге көмектеседі деп үміттенемін.
Содан кейін, docker-compose.yml жазғаннан кейін, досымның кеңесімен мен қолдауды қостым
Бұл үлгі жаңадан бастағандарға керемет және қуатты, бірақ C++ сияқты ебедейсіз тілде REST API қосымшаларын жасаудың қиын жолында көмектеседі деп үміттенемін.
Сонымен қатар, мен мұнда оқуға кеңес беремін
Ақпарат көзі: www.habr.com