mifは、バックエンド マイクロサービス開発用に設計された C++11 Web アプリケーション フレームワークです。フレームワークは追加のタイプのメタ情報を利用します。
1.5.1
注: master ブランチは積極的に開発されており、運用環境での使用には最新のリリースを使用してください。
最後に 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 フォルダーにあります。例の詳細なドキュメントは wiki にあります。
サーバ:
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 サーバーの動作を示します。詳細については、「Web サービス。追加」の章を参照してください。
ソースコード
説明
「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)
ソースコード
説明
前の例と比較すると、この例ではインターフェイスの継承が追加されています。実装では、階層外のインターフェイスをクエリできます。
ソースコード
説明
「Visitor」の例では、インターフェイス メソッドのリモート コールバックのメカニズムを示します。これは、パブリッシュ/サブスクライブ ベースのアプリケーションの開始点として使用できます。
ソースコード
説明
この例では、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 "
ソースコード
説明
この例では、2 つのマイクロサービス間の通信を示します (この例は 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 を使用してアプリケーションを構築するための開始点として使用できます。