Katika nakala hii nitazungumza juu ya jinsi nilivyounda template (cookiecutter) na kuweka mazingira ya kuandika huduma ya REST API katika C ++ kwa kutumia docker/docker-compose na msimamizi wa kifurushi cha conan.
Wakati wa hackathon iliyofuata, ambayo nilishiriki kama msanidi wa nyuma, swali liliibuka juu ya nini cha kutumia kuandika huduma ndogo inayofuata. Kila kitu ambacho kimeandikwa hadi sasa kiliandikwa na mimi na wangu
Kwa hiyo, tulikuwa tunakabiliwa na kazi ya kuandika huduma ya juu ya mzigo, kazi kuu ambayo ilikuwa ni kutayarisha data inayokuja kwake na kuiandika kwenye hifadhidata. Na baada ya mapumziko mengine ya moshi, rafiki alipendekeza kwamba mimi, kama msanidi wa C ++, niandike huduma hii kwa kutumia faida. Kujadili hii ni kwamba itakuwa haraka, yenye tija zaidi, na kwa ujumla, jury itafurahishwa na jinsi tunavyojua jinsi ya kusimamia rasilimali za timu. Ambayo nilijibu kwamba sijawahi kufanya mambo kama haya katika C++ na ningeweza kutumia kwa urahisi saa 20+ zilizobaki kutafuta, kukusanya na kuunganisha maktaba zinazofaa. Kwa ufupi, nilicheka. Hiyo ndio tuliamua na tukakamilisha kwa utulivu kila kitu kwenye Python.
Sasa, wakati wa kujitenga kwa kulazimishwa, niliamua kujua jinsi ya kuandika huduma katika C ++. Jambo la kwanza kufanya lilikuwa kuamua juu ya maktaba inayofaa. Chaguo langu lilianguka
conanfile.txt
[inahitaji]poco/1.9.3
libpq/11.5
na kwa amri rahisi "conan install ." kufunga maktaba muhimu. Kwa kawaida, ilikuwa ni lazima pia kufanya mabadiliko kwa
CMakeLists.txt
include(build/conanbuildinfo.cmake)
conan_basic_setup()
target_link_libraries(<target_name> ${CONAN_LIBS})
Baada ya hapo, nilianza kutafuta maktaba ya kufanya kazi na PostgreSQL, kwani ndiyo ambayo nilikuwa na uzoefu mdogo wa kufanya kazi nayo, na pia ndiyo huduma zetu za Python ziliingiliana nayo. Na unajua nilichojifunza? Iko katika POCO! Lakini conan hajui kuwa iko kwenye POCO na hajui jinsi ya kuijenga; kuna faili ya usanidi iliyopitwa na wakati kwenye hazina (tayari nimeandika juu ya kosa hili kwa waundaji wa POCO). Hii inamaanisha itabidi utafute maktaba nyingine.
Na kisha chaguo langu likaanguka kwenye maktaba isiyojulikana sana
Hatua inayofuata ilikuwa kuandika kiolezo cha huduma ambacho kinaweza kushughulikia maombi.
Ni lazima turithi darasa letu la TemplateServerApp kutoka Poco::Util::ServerApplication na kubatilisha mbinu kuu.
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;
}
Katika njia kuu lazima tuweke vigezo: bandari, idadi ya nyuzi na ukubwa wa foleni. Na muhimu zaidi, lazima ubainishe kidhibiti kwa maombi yanayoingia. Hii inafanywa kwa kuunda kiwanda
TemplateRequestHandlerFactory
class TemplateRequestHandlerFactory : public HTTPRequestHandlerFactory
{
public:
virtual HTTPRequestHandler* createRequestHandler(const HTTPServerRequest & request)
{
return new TemplateServerAppHandler;
}
};
Kwa upande wangu, inaunda kidhibiti sawa kila wakati - TemplateServerAppHandler. Hapa ndipo tunaweza kuweka mantiki ya biashara yetu.
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();
}
};
Pia niliunda kiolezo cha darasa kufanya kazi na PostgreSQL. Ili kufanya SQL rahisi, kama vile kuunda meza, kuna njia TekelezaSQL(). Kwa hoja ngumu zaidi au urejeshaji data, itabidi upate muunganisho kupitia GetConnection() na utumie API ya libpg. (Labda baadaye nitarekebisha dhuluma hii).
Database
#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;
};
Vigezo vyote vya kuunganisha kwenye hifadhidata vinachukuliwa kutoka kwa mazingira, kwa hivyo unahitaji pia kuunda na kusanidi faili ya .env.
.a
DATABASE_NAME=template
DATABASE_USER=user
DATABASE_PASSWORD=password
DATABASE_HOST=postgres
DATABASE_PORT=5432
Unaweza kuona nambari zote kwenye
Na sasa inakuja hatua ya mwisho ya kuandika faili ya docker na docker-compose.yml. Kuwa waaminifu, hii ilichukua muda mwingi, na si tu kwa sababu mimi ni noob, kwa sababu ilikuwa ni lazima kujenga upya maktaba kila wakati, lakini kwa sababu ya mitego ya conan. Kwa mfano, ili conan kupakua, kusakinisha na kujenga vitegemezi vinavyohitajika, haitoshi kupakua "conan install .", inahitaji pia kupitisha parameta -s compiler.libcxx=libstdc++11, vinginevyo. una hatari ya kupata rundo la makosa katika hatua ya kuunganisha programu yako. Nimekuwa nikikwama na hitilafu hii kwa saa kadhaa na natumaini makala hii itasaidia watu wengine kutatua tatizo hili kwa muda mfupi.
Kisha, baada ya kuandika docker-compose.yml, kwa ushauri wa rafiki yangu, niliongeza msaada
Natumai kiolezo hiki kitasaidia wanaoanza kwenye njia yao ngumu ya kutengeneza programu za REST API katika lugha kuu na yenye nguvu, lakini lugha ngumu kama C++.
Pia, ninapendekeza sana kusoma hapa
Chanzo: mapenzi.com