Ebben a cikkben arról fogok beszélni, hogyan hoztam létre egy sablont (cookiecutter) és állítottam be egy környezetet egy REST API szolgáltatás írásához C++ nyelven a docker/docker-compose és a conan csomagkezelő segítségével.
A következő hackathon során, amelyen háttérfejlesztőként vettem részt, felmerült a kérdés, hogy mivel írjam meg a következő mikroszolgáltatást. Mindent, amit eddig írtam, én és az én írtam
Így egy nagy terhelésű szolgáltatás megírásával álltunk szemben, melynek fő feladata a hozzá érkező adatok előfeldolgozása és adatbázisba írása volt. És egy újabb füstszünet után egy barátom azt javasolta, hogy C++ fejlesztőként írjam meg ezt a szolgáltatást a profik segítségével. Ezzel az érvel, hogy gyorsabb, produktívabb lesz, és általában a zsűri el lesz ragadtatva attól, hogyan tudjuk kezelni a csapat erőforrásait. Mire azt válaszoltam, hogy soha nem csináltam ilyeneket C++-ban, és a maradék 20+ órát nyugodtan fordíthatnám megfelelő könyvtárak keresésére, összeállítására és linkelésére. Egyszerűen fogalmazva, kiakadtam. Így döntöttünk, és nyugodtan befejeztünk mindent Pythonban.
Most, a kényszerű önizoláció során úgy döntöttem, kitalálom, hogyan írjak szolgáltatásokat C++ nyelven. Az első dolga a megfelelő könyvtár kiválasztása volt. A választásom esett
conanfile.txt
[szükséges]poco/1.9.3
libpq/11.5
és egy egyszerű "conan install" paranccsal. telepítse a szükséges könyvtárakat. Természetesen ezen is változtatni kellett
CMakeLists.txt
include(build/conanbuildinfo.cmake)
conan_basic_setup()
target_link_libraries(<target_name> ${CONAN_LIBS})
Ezt követően elkezdtem keresni egy könyvtárat a PostgreSQL-lel való együttműködéshez, mivel ezzel kevés tapasztalatom volt, és a Python szolgáltatásaink is ezzel kommunikáltak. És tudod mit tanultam? A POCO-ban van! De a conan nem tudja, hogy a POCO-ban van, és nem tudja, hogyan kell felépíteni; van egy elavult konfigurációs fájl a tárolóban (erről a hibáról már írtam a POCO készítőinek). Ez azt jelenti, hogy másik könyvtárat kell keresnie.
És akkor a választásom egy kevésbé népszerű könyvtárra esett
A következő lépés egy szolgáltatássablon megírása volt, amely képes feldolgozni a kéréseket.
A TemplateServerApp osztályunkat a Poco::Util::ServerApplication-től kell örökölnünk, és felül kell bírálnunk a fő metódust.
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;
}
A fő metódusban be kell állítani a paramétereket: port, szálak száma és a sor mérete. És ami a legfontosabb, meg kell adnia a bejövő kérések kezelőjét. Ez egy gyár létrehozásával történik
TemplateRequestHandlerFactory
class TemplateRequestHandlerFactory : public HTTPRequestHandlerFactory
{
public:
virtual HTTPRequestHandler* createRequestHandler(const HTTPServerRequest & request)
{
return new TemplateServerAppHandler;
}
};
Az én esetemben egyszerűen ugyanazt a kezelőt hozza létre minden alkalommal - TemplateServerAppHandler. Ide helyezhetjük üzleti logikánkat.
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();
}
};
Létrehoztam egy osztálysablont is a PostgreSQL-lel való együttműködéshez. Az egyszerű SQL végrehajtásához, például egy tábla létrehozásához, létezik egy módszer ExecuteSQL(). Bonyolultabb lekérdezésekhez vagy adatlekéréshez kapcsolatot kell létesítenie ezen keresztül Kapcsolódás() és használja a libpg API-t. (Talán később kijavítom ezt az igazságtalanságot).
adatbázis
#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;
};
Az adatbázishoz való csatlakozáshoz szükséges összes paraméter a környezetből származik, ezért létre kell hozni és be kell állítani az .env fájlt is
.NS
DATABASE_NAME=template
DATABASE_USER=user
DATABASE_PASSWORD=password
DATABASE_HOST=postgres
DATABASE_PORT=5432
Az összes kódot megtekintheti a címen
És most jön a dockerfile és a docker-compose.yml megírásának utolsó szakasza. Hogy őszinte legyek, ez a legtöbb időt igénybe vette, és nem csak azért, mert noob vagyok, mert minden alkalommal újra kellett építeni a könyvtárakat, hanem a conan buktatói miatt is. Például ahhoz, hogy a conan letöltse, telepítse és felépítse a szükséges függőségeket, nem elég letöltenie a „conan install .-t”, át kell adnia a -s compiler.libcxx=libstdc++11 paramétert is, ellenkező esetben azt kockáztatja, hogy egy csomó hibát kap az alkalmazás összekapcsolási szakaszában. Több órája elakadtam ezzel a hibával, és remélem, hogy ez a cikk segít másoknak rövidebb idő alatt megoldani ezt a problémát.
Ezután, miután megírtam a docker-compose.yml fájlt, barátom tanácsára támogatást adtam hozzá
Remélem, ez a sablon segíteni fog a kezdőknek a REST API-alkalmazások fejlesztésének nehéz útján a nagyszerű és hatékony, de olyan ügyetlen nyelven, mint a C++.
Ezen kívül nagyon ajánlom itt olvasni
Forrás: will.com