mif 는 백엔드 마이크로서비스 개발을 위해 설계된 C++11 웹 애플리케이션 프레임워크입니다. 프레임워크는 추가 유형 메타 정보를 사용합니다.
1.5.1
참고: 마스터 브랜치는 적극적으로 개발되고 있으므로 프로덕션 용도로 최신 릴리스를 사용하십시오.
gcc 13.2에서 마지막으로 테스트되었습니다.
Linux(Ubuntu 23.10에서 마지막으로 테스트됨)
git clone https://github.com/tdv/mif.git
cd mif
./download_third_party.sh
mkdir build
cd build
cmake ..
make
make install
참고: Ubuntu에서는 liblz4-dev, pkgconf, bison, flex와 같은 추가 패키지를 설치해야 할 수도 있습니다.
CMAKE_INSTALL_PREFIX를 사용하여 설치 디렉터리를 선택할 수 있습니다.
mif 가 빌드된 후 예제를 빌드할 수 있습니다.
cd mif /examples/{sample_project}
mkdir build
cd build
cmake ..
make
참고: 애플리케이션을 개발하려면 애플리케이션 템플릿을 사용할 수 있습니다. mif 프로젝트를 다운로드한 후 다음 단계를 따르세요.
cd mif /template
mkdir build
cd build
cmake ..
make
그런 다음 이 템플릿을 변경하여 자신만의 애플리케이션을 만들 수 있습니다. 또한 템플릿에서 수행된 예제를 사용할 수 있습니다. 예제는 완전히 완료되었으며 빌드 자체를 위한 스크립트가 있습니다. 모두 _docs 폴더에 있습니다. 위키에서 예제에 대한 자세한 문서를 찾을 수 있습니다.
섬기는 사람:
cd mif /exammples/{sample_project}/bin
./{sample_project}_server
고객:
cd mif /exammples/{sample_project}/bin
./{sample_project}_client
예제 실행에 대한 자세한 내용을 보려면 --help를 사용하십시오.
소스 코드
설명
이 예에서는 간단한 HTTP 에코 서버의 작업을 보여줍니다. HTTP 에코 서버
// mif
# include < mif /application/http_server.h >
# include < mif /common/log.h >
# include < mif /net/http/constants.h >
class Application
: public mif ::Application::HttpServer
{
public:
using HttpServer::HttpServer;
private:
// mif .Application.HttpServer
virtual void Init ( mif ::Net::Http::ServerHandlers &handlers) override final
{
handlers[ " / " ] = [] ( mif ::Net::Http::IInputPack const &request,
mif ::Net::Http::IOutputPack &response)
{
auto data = request. GetData ();
mif _LOG (Info) << " Process request " " << request. GetPath () << request. GetQuery () << " "t Data: "
<< (data. empty () ? std::string{ " null " } : std::string{ std::begin (data), std::end (data)});
response. SetCode ( mif ::Net::Http::Code::Ok);
response. SetHeader ( mif ::Net::Http::Constants::Header::Connection::Value,
mif ::Net::Http::Constants::Value::Connection::Close::Value);
response. SetData ( std::move (data));
};
}
};
int main ( int argc, char const **argv)
{
return mif ::Application::Run<Application>(argc, argv);
}
시험
curl -iv -X POST " http://localhost:55555/ " -d ' Test data '
소스 코드
설명
이 예는 원시 HTTP 요청과 HTTP에 의한 mif RPC를 처리하기 위한 이중 인터페이스를 갖춘 HTTP 서버의 작업을 보여줍니다. 자세한 내용은 "웹 서비스. 추가" 장에서 확인할 수 있습니다.
소스 코드
설명
"Hello World" 예제에서는 데이터 직렬화를 위해 Boost.archives를 사용하여 인터페이스 기반 RPC 마샬링 및 TCP 통신을 갖춘 기본 클라이언트-서버 애플리케이션을 보여줍니다.
RPC를 사용하여 클라이언트-서버 애플리케이션을 구축하기 위한 기본 단계
공통 인터페이스
// STD
# include < string >
// mif
# include < mif /service/iservice.h >
namespace Service
{
struct IHelloWorld
: public mif ::Service::Inherit< mif ::Service::IService>
{
virtual void AddWord (std::string const &word) = 0;
virtual std::string GetText () const = 0;
virtual void Clean () = 0;
};
} // namespace Service
공통 인터페이스 메타정보
// STD
# include < string >
// mif
# include < mif /remote/ps.h >
// THIS
# include " common/interface/ihello_world.h "
namespace Service
{
namespace Meta
{
using namespace ::Service ;
mif _REMOTE_PS_BEGIN (IHelloWorld)
mif _REMOTE_METHOD (AddWord)
mif _REMOTE_METHOD (GetText)
mif _REMOTE_METHOD (Clean)
mif _REMOTE_PS_END ()
} // namespace Meta
} // namespace Service
mif _REMOTE_REGISTER_PS (Service::Meta::IHelloWorld)
서버 인터페이스 구현
...
// mif
# include < mif /service/creator.h >
// THIS
# include " common/id/service.h "
# include " common/interface/ihello_world.h "
namespace Service
{
namespace Detail
{
namespace
{
class HelloWorld
: public IHelloWorld
{
public:
...
private:
...
// IHelloWorld
virtual void AddWord (std::string const &word) override final
{
...
}
virtual std::string GetText () const override final
{
...
}
virtual void Clean () override final
{
...
}
};
} // namespace
} // namespace Detail
} // namespace Service
mif _SERVICE_CREATOR
(
::Service::Id::HelloWorld,
::Service::Detail::HelloWorld
)
서버 애플리케이션
// mif
# include < mif /application/tcp_service.h >
// COMMON
# include " common/id/service.h "
# include " common/ps/ihello_world.h "
class Application
: public mif ::Application::TcpService
{
public:
using TcpService::TcpService;
private:
// mif .Application.TcpService
virtual void Init ( mif ::Service::FactoryPtr factory) override final
{
factory-> AddClass <Service::Id::HelloWorld>();
}
};
int main ( int argc, char const **argv)
{
return mif ::Application::Run<Application>(argc, argv);
}
클라이언트 애플리케이션
// mif
# include < mif /application/tcp_service_client.h >
# include < mif /common/log.h >
// COMMON
# include " common/ps/ihello_world.h "
class Application
: public mif ::Application::TcpServiceClient
{
public:
using TcpServiceClient::TcpServiceClient;
private:
// mif .Application.TcpServiceClient
virtual void Init ( mif ::Service::IFactoryPtr factory) override final
{
auto service = factory-> Create <Service::IHelloWorld>( " HelloWorld " );
mif _LOG (Info) << " Add words. " ;
service-> AddWord ( " Hello " );
service-> AddWord ( " World " );
service-> AddWord ( " !!! " );
mif _LOG (Info) << " Result from server: " " << service-> GetText () << " " " ;
mif _LOG (Info) << " Clean. " ;
service-> Clean ();
mif _LOG (Info) << " Result from server: " " << service-> GetText () << " " " ;
}
};
int main ( int argc, char const **argv)
{
return mif ::Application::Run<Application>(argc, argv);
}
소스 코드
설명
이 예는 "Hello World"와 동일합니다. 차이점은 사용자 정의 데이터 구조를 매개변수로 사용하여 원격 메서드를 호출하고 값을 반환한다는 것입니다. 프로젝트 구조는 이전 프로젝트 예시와 동일하며, 사용자 정의 데이터 구조 정의와 메타정보만 추가했습니다.
사용자 데이터 구조
// STD
# include < cstdint >
# include < map >
# include < string >
namespace Service
{
namespace Data
{
using ID = std::string;
struct Human
{
std::string name;
std::string lastName;
std:: uint32_t age = 0 ;
};
enum class Position
{
Unknown,
Developer,
Manager
};
struct Employee
: public Human
{
Position position = Position::Unknown;
};
using Employees = std::map<ID, Employee>;
} // namespace Data
} // namespace Service
메타정보
// mif
# include < mif /reflection/reflect_type.h >
// THIS
# include " common/data/data.h "
namespace Service
{
namespace Data
{
namespace Meta
{
mif _REFLECT_BEGIN (Human)
mif _REFLECT_FIELD (name)
mif _REFLECT_FIELD (lastName)
mif _REFLECT_FIELD (age)
mif _REFLECT_END ()
mif _REFLECT_BEGIN (Position)
mif _REFLECT_FIELD (Unknown)
mif _REFLECT_FIELD (Developer)
mif _REFLECT_FIELD (Manager)
mif _REFLECT_END ()
mif _REFLECT_BEGIN (Employee, Human)
mif _REFLECT_FIELD (position)
mif _REFLECT_END ()
} // namespace Meta
} // namespace Data
} // namespace Service
mif _REGISTER_REFLECTED_TYPE (::Service::Data::Meta::Human)
mif _REGISTER_REFLECTED_TYPE(::Service::Data::Meta::Position)
mif _REGISTER_REFLECTED_TYPE(::Service::Data::Meta::Employee)
소스 코드
설명
이전 예제와 비교하여 이것은 인터페이스 상속을 추가합니다. 구현 시 계층 구조를 벗어난 인터페이스를 쿼리할 수 있습니다.
소스 코드
설명
"방문자" 예제에서는 인터페이스 메서드에 대한 원격 콜백 메커니즘을 보여줍니다. 이는 게시/구독 기반 애플리케이션의 시작점으로 사용될 수 있습니다.
소스 코드
설명
이 예에서는 HTTP 서버의 Json API(CRUD 작업)를 보여줍니다.
시험
curl -i -X POST " http://localhost:55555/employee/create " -d ' {"name":"Ivan", "lastName":"Ivanov","age":33,"email":"[email protected]","position":"Developer","rate":200000.00} '
curl -i " http://localhost:55555/employee/read?id=1 "
curl -i " http://localhost:55555/employee/update?id=1 " -d ' {"name":"Ivan", "lastName":"Ivanov","age":33,"email":"[email protected]","position":"Developer","rate":220000.00} '
curl -i " http://localhost:55555/employee/list?limit=2&offset=0 "
curl -i " http://localhost:55555/employee/delete?id=1 "
소스 코드
설명
이 예에서는 두 마이크로서비스 간의 통신을 보여줍니다(예제는 http crud의 더 강력한 버전입니다). 시험
./storage —config=storage.xml
./service --config=service.xml
curl -i -X POST " http://localhost:55555/employee/create " -d ' {"name":"Ivan", "lastName":"Ivanov","age":33,"email":"[email protected]","position":"Developer","rate":200000.00} '
curl -i " http://localhost:55555/employee/read?id=1 "
curl -i " http://localhost:55555/employee/update?id=1 " -d ' {"name":"Ivan", "lastName":"Ivanov","age":33,"email":"[email protected]","position":"Developer","rate":220000.00} '
curl -i " http://localhost:55555/employee/list?limit=2&offset=0 "
curl -i " http://localhost:55555/employee/delete?id=1 "
소스 코드
설명
이 예에서는 C++ 데이터 구조체 반영 메커니즘을 보여줍니다. 이는 직렬화, ORM 및 REST API를 사용하여 애플리케이션을 구축하기 위한 시작점으로 사용할 수 있습니다.