Yn dit artikel sil ik prate oer hoe't ik in sjabloan makke (cookiecutter) en in omjouwing ynstelle foar it skriuwen fan in REST API-tsjinst yn C ++ mei docker/docker-compose en de conan-pakketbehearder.
Tidens de folgjende hackathon, dêr't ik as backend-ûntwikkelder oan meidie, kaam de fraach oer wat te brûken om de folgjende mikrotsjinst te skriuwen. Alles wat oant no ta skreaun is, is skreaun troch my en myn
Dat, wy waarden konfrontearre mei de taak fan it skriuwen fan in tsjinst mei hege lading, wêrfan de haadtaak wie om de gegevens dy't derby komme foar te ferwurkjen en te skriuwen nei de databank. En nei in oare reekpauze suggerearre in freon dat ik, as C++-ûntwikkelder, dizze tsjinst skriuw mei de profs. Dit argumintearje is dat it rapper, produktiver sil wêze, en yn 't algemien sil de sjuery bliid wêze mei hoe't wy witte hoe't wy de middels fan it team kinne beheare. Dêrop antwurde ik dat ik sokke dingen noait dien hie yn C++ en de oerbleaune 20+ oeren maklik besteegje koe oan it sykjen, kompilearjen en keppeljen fan gaadlike bibleteken. Simply sette, ik kip út. Dat hawwe wy besletten en rêstich alles yn Python ôfmakke.
No, tidens de twongen selsisolaasje, besleat ik út te finen hoe't jo tsjinsten yn C ++ skriuwe kinne. It earste ding om te dwaan wie beslute oer in geskikte biblioteek. Myn kar foel op
conanfile.txt
[fereasket] poco/1.9.3
libpq/11.5
en mei in ienfâldich kommando "conan install." ynstallearje de nedige biblioteken. Fansels wie it ek nedich om feroarings oan te bringen
CMakeLists.txt
include(build/conanbuildinfo.cmake)
conan_basic_setup()
target_link_libraries(<target_name> ${CONAN_LIBS})
Dêrnei begon ik op syk nei in bibleteek om te wurkjen mei PostgreSQL, om't it dejinge wie wêr't ik net folle ûnderfining mei hie, en it wie ek dejinge dy't ús Python-tsjinsten ynteraksje mei. En witsto wat ik leard haw? It is yn POCO! Mar conan wit net dat it yn POCO is en wit net hoe't it moat bouwe; d'r is in ferâldere konfiguraasjetriem yn 'e repository (ik haw al skreaun oer dizze flater oan' e makkers fan POCO). Dit betsjut dat jo nei in oare bibleteek moatte sykje.
En doe foel myn kar op in minder populêre bibleteek
De folgjende stap wie om in tsjinstsjabloan te skriuwen dat fersiken kin ferwurkje.
Wy moatte ús TemplateServerApp-klasse erve fan Poco :: Util :: ServerApplication en de haadmetoade oerskriuwe.
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;
}
Yn 'e haadmetoade moatte wy de parameters ynstelle: poarte, oantal triedden en wachtrige grutte. En it wichtichste, jo moatte in handler opjaan foar ynkommende oanfragen. Dit wurdt dien troch it meitsjen fan in fabryk
TemplateRequestHandlerFactory
class TemplateRequestHandlerFactory : public HTTPRequestHandlerFactory
{
public:
virtual HTTPRequestHandler* createRequestHandler(const HTTPServerRequest & request)
{
return new TemplateServerAppHandler;
}
};
Yn myn gefal makket it gewoan elke kear deselde handler - TemplateServerAppHandler. Dit is wêr't wy ús bedriuwslogika kinne pleatse.
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();
}
};
Ik haw ek in klassesjabloan makke om te wurkjen mei PostgreSQL. Om ienfâldige SQL út te fieren, lykas it meitsjen fan in tabel, is d'r in metoade ExecuteSQL(). Foar mear komplekse fragen of gegevens opheljen moatte jo in ferbining krije fia GetConnection() en brûk de libpg API. (Miskien sil ik letter dit ûnrjocht korrigearje).
Databank
#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;
};
Alle parameters foar it ferbinen mei de databank wurde út 'e omjouwing nommen, dus jo moatte ek it .env-bestân oanmeitsje en konfigurearje
.en V
DATABASE_NAME=template
DATABASE_USER=user
DATABASE_PASSWORD=password
DATABASE_HOST=postgres
DATABASE_PORT=5432
Jo kinne sjen alle koade op
En no komt it lêste stadium fan it skriuwen fan de dockerfile en docker-compose.yml. Om earlik te wêzen, dit duorre de measte tiid, en net allinnich om't ik bin in noob, om't it wie nedich om wer opbouwen fan de bibleteken eltse kear, mar fanwege de falkûlen fan conan. Bygelyks, om conan de nedige ôfhinklikens te downloaden, te ynstallearjen en te bouwen, is it net genôch om "conan install ." te downloaden, it moat ek de parameter -s compiler.libcxx=libstdc++11 trochjaan, oars jo riskearje in protte flaters te krijen by it keppeljen fan jo applikaasje. Ik bin ferskate oeren fêst sitten mei dizze flater en ik hoopje dat dit artikel oare minsken sil helpe om dit probleem yn minder tiid op te lossen.
Folgjende, nei it skriuwen fan docker-compose.yml, op advys fan myn freon, haw ik stipe tafoege
Ik hoopje dat dit sjabloan begjinners sil helpe op har drege paad fan it ûntwikkeljen fan REST API-applikaasjes yn 'e grutte en krêftige, mar sa'n ûnhandige taal lykas C ++.
Ek ried ik tige oan om hjir te lêzen
Boarne: www.habr.com