Yn yr erthygl hon byddaf yn siarad am sut y creais dempled (cookiecutter) a sefydlu amgylchedd ar gyfer ysgrifennu gwasanaeth API REST yn C ++ gan ddefnyddio docker/docker-compose a'r rheolwr pecyn conan.
Yn ystod yr hacathon nesaf, y cymerais ran ynddo fel datblygwr backend, cododd y cwestiwn beth i'w ddefnyddio i ysgrifennu'r microwasanaeth nesaf. Mae popeth sydd wedi'i ysgrifennu hyd yn hyn wedi'i ysgrifennu gennyf fi a fy
Felly, roeddem yn wynebu'r dasg o ysgrifennu gwasanaeth llwyth uchel, a'r prif dasg oedd rhag-brosesu'r data a oedd yn dod ato a'i ysgrifennu i'r gronfa ddata. Ac ar ôl seibiant mwg arall, awgrymodd ffrind fy mod i, fel datblygwr C ++, yn ysgrifennu'r gwasanaeth hwn gan ddefnyddio'r manteision. Gan ddadlau y bydd hyn yn gyflymach, yn fwy cynhyrchiol, ac yn gyffredinol, bydd y rheithgor wrth eu bodd â sut rydym yn gwybod sut i reoli adnoddau'r tîm. Atebais nad oeddwn erioed wedi gwneud pethau o'r fath yn C++ ac y gallwn yn hawdd neilltuo'r 20+ awr sy'n weddill i chwilio, llunio a chysylltu llyfrgelloedd addas. Yn syml, yr wyf yn cyweirio allan. Dyna beth wnaethon ni benderfynu arno a chwblhau popeth yn bwyllog yn Python.
Nawr, yn ystod yr hunan-ynysu gorfodol, penderfynais ddarganfod sut i ysgrifennu gwasanaethau yn C ++. Y peth cyntaf i'w wneud oedd penderfynu ar lyfrgell addas. Syrthiodd fy newis ymlaen
conanfile.txt
[angen]poco/1.9.3
libpq/11.5
a gyda gorchymyn syml " conan install ." gosod y llyfrgelloedd angenrheidiol. Yn naturiol, roedd hefyd angen gwneud newidiadau i
CMakeLists.txt
include(build/conanbuildinfo.cmake)
conan_basic_setup()
target_link_libraries(<target_name> ${CONAN_LIBS})
Ar ôl hynny, dechreuais chwilio am lyfrgell i weithio gyda PostgreSQL, gan mai dyma'r un nad oedd gen i fawr o brofiad o weithio ag ef, a dyma hefyd oedd yr un yr oedd ein gwasanaethau Python yn rhyngweithio ag ef. Ac ydych chi'n gwybod beth ddysgais i? Mae yn POCO! Ond nid yw Conan yn gwybod ei fod yn POCO ac nid yw'n gwybod sut i'w adeiladu; mae ffeil ffurfweddu hen ffasiwn yn yr ystorfa (rwyf eisoes wedi ysgrifennu am y gwall hwn at grewyr POCO). Mae hyn yn golygu y bydd yn rhaid i chi chwilio am lyfrgell arall.
Ac yna disgynnodd fy newis ar lyfrgell lai poblogaidd
Y cam nesaf oedd ysgrifennu templed gwasanaeth a all brosesu ceisiadau.
Rhaid inni etifeddu ein dosbarth TemplateServerApp gan Poco ::Util ::ServerApplication a diystyru'r prif ddull.
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 y prif ddull rhaid inni osod y paramedrau: porthladd, nifer yr edafedd a maint y ciw. Ac yn bwysicaf oll, rhaid i chi nodi triniwr ar gyfer ceisiadau sy'n dod i mewn. Gwneir hyn trwy greu ffatri
TemplateRequestHandlerFactory
class TemplateRequestHandlerFactory : public HTTPRequestHandlerFactory
{
public:
virtual HTTPRequestHandler* createRequestHandler(const HTTPServerRequest & request)
{
return new TemplateServerAppHandler;
}
};
Yn fy achos i, yn syml, mae'n creu'r un triniwr bob tro - TemplateServerAppHandler. Dyma lle gallwn osod ein rhesymeg busnes.
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();
}
};
Creais hefyd dempled dosbarth i weithio gyda PostgreSQL. I berfformio SQL syml, fel creu tabl, mae yna ddull GweithreduSQL(). Ar gyfer ymholiadau mwy cymhleth neu adalw data, bydd yn rhaid i chi gael cysylltiad trwy GetConnection() a defnyddio'r API libpg. (Efallai yn ddiweddarach y byddaf yn cywiro'r anghyfiawnder hwn).
Cronfa Ddata
#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;
};
Cymerir yr holl baramedrau ar gyfer cysylltu â'r gronfa ddata o'r amgylchedd, felly mae angen i chi hefyd greu a ffurfweddu'r ffeil .env
.env
DATABASE_NAME=template
DATABASE_USER=user
DATABASE_PASSWORD=password
DATABASE_HOST=postgres
DATABASE_PORT=5432
Gallwch weld y cod i gyd yn
Ac yn awr daw'r cam olaf o ysgrifennu'r dockerfile a docker-compose.yml. A dweud y gwir, cymerodd hyn y rhan fwyaf o'r amser, ac nid yn unig oherwydd fy mod yn noob, oherwydd bod angen ailadeiladu'r llyfrgelloedd bob tro, ond oherwydd peryglon conan. Er enghraifft, er mwyn i conan lawrlwytho, gosod ac adeiladu'r dibyniaethau angenrheidiol, nid yw'n ddigon iddo lawrlwytho "conan install .", mae angen iddo hefyd basio'r paramedr -s compiler.libcxx=libstdc++11, fel arall rydych mewn perygl o gael llawer o wallau ar y cam cysylltu eich cais. Rwyf wedi bod yn sownd â'r gwall hwn ers sawl awr a gobeithio y bydd yr erthygl hon yn helpu pobl eraill i ddatrys y broblem hon mewn llai o amser.
Nesaf, ar ôl ysgrifennu docker-compose.yml, ar gyngor fy ffrind, ychwanegais gefnogaeth
Rwy'n gobeithio y bydd y templed hwn yn helpu dechreuwyr ar eu llwybr anodd o ddatblygu cymwysiadau REST API yn y gwych a'r pwerus, ond iaith mor drwsgl fel C ++.
Hefyd, rwy'n argymell darllen yma yn fawr
Ffynhonnell: hab.com