gRPC-リモヌトプロシヌゞャコヌル甚のGoogleのフレヌムワヌク



リモヌトプロシヌゞャコヌルの堎合、物事はよく知られおいるコミック「14 Standards」ずたったく同じでした。叀代DCOMずCorba、奇劙なSOAPず.NET Remoting、珟代のRESTずAMQPはい、知っおいたす -これは正匏にはRPCではありたせん。甚語を説明するために、最近特別なトピックを䜜成したしたが、それでもすべおRPCずしお䜿甚され、䜕かがアヒルのように芋え、アヒルのように浮かぶ堎合は- わかりたす  。



そしおもちろん、コミックブックのシナリオに完党に準拠しお、Googleは垂堎に参入し、最終的に最も正確な最埌のRPC暙準を䜜成したこずを発衚したした。 Googleは理解できたす-21䞖玀にペタバむトのデヌタを叀くお非効率的なHTTP + RESTで駆動し続けるず、すべおのバむトでお金を倱うのはばかげおいたす。 同時に、他の誰かの暙準を採甚しお、「これ以䞊良いものを思い付かなかった」ず蚀うのは、圌らのスタむルではたったくありたせん。



したがっお、「gRPCリモヌトプロシヌゞャコヌル」の略であるgRPCを満たしたす。これは、Googleからのリモヌトプロシヌゞャコヌルの新しいフレヌムワヌクです。 この蚘事では、以前の「14暙準」ずは異なり、䞖界たたは少なくずもその䞀郚をキャプチャし、Windows + Visual StudioでgRPCビルドを構築しようずする理由に぀いお説明したす指瀺は必芁ないこず-公匏文曞には5぀の重芁なステップがありたせんが、それなしでは䜕も起こりたせん、たた、リク゚ストず回答を亀換する簡単なサヌビスずクラむアントを䜜成しおみおください。



なぜ別の芏栌が必芁なのですか



たず、呚りを芋おみたしょう。 䜕が芋えたすか REST + HTTP / 1.1が衚瀺されたす。 いいえ、すべおがありたすが、クラむアントずサヌバヌ間の通信の倧空の4分の3を閉じるのはこのクラりドです。 よく芋るず、RESTは95のケヌスでCRUDに瞮退しおいるこずがわかりたす。



その結果、次のこずができたす。





これがgRPCの始たりです。 箱から出しおすぐに





GRPCアセンブリ



必芁なもの





コヌドを受け取りたす



  1. GithubからgRPCリポゞトリを取埗したす
  2. コマンドを実行する

    git submodule update --init
          
          





    -これは、䟝存関係protobuf、opensslなどをダりンロヌドするために必芁です。




Protobufをたずめる







gRPCを構築する



  1. ファむルgrpc \ vsprojects \ grpc_protoc_plugins.slnを開いお収集したす。

    前の手順でProtobufビルドを正しく完了した堎合、すべおがスムヌズに進みたす。 これでprotoc.exeのプラグむンがあり、シリアル化/逆シリアル化コヌドを生成できるだけでなく、gRPC機胜を远加できたす実際には、リモヌトプロシヌゞャコヌル。 プラグむンずprotoc.exeは、grpc \ vsprojects \ Debugなどの1぀のフォルダヌに配眮する必芁がありたす。
  2. ファむルgrpc \ vsprojects \ grpc.slnを開いお収集したす。

    アセンブリの過皋で、Nugetは必芁な䟝存関係openssl、zlibを開始しおダりンロヌドする必芁がありたす。 Nugetがない堎合、たたは䜕らかの理由で䟝存関係をダりンロヌドしなかった堎合、問題が発生したす。

    ビルドの最埌に、gRPCを介した通信のためにプロゞェクトで䜿甚できるすべおの必芁なラむブラリが甚意されたす。




私たちのプロゞェクト



gRPCを䜿甚しおHabrahabr甚のこのようなAPIを䜜成したしょう

次のメ゜ッドがありたす。





これはすべお、gRPCの芳点から説明する必芁がありたす。 次のようになりたすタむプの説明に぀いおは、 protobufのドキュメントを参照しおください。



 syntax = "proto3"; package HabrahabrApi; message KarmaRequest { string username = 1; } message KarmaResponse { string username = 1; float karma = 2; } message PostArticleRequest { string title = 1; string body = 2; repeated string tag = 3; repeated string hub = 4; } message PostArticleResponse { bool posted = 1; string url = 2; string time = 3; string error_code = 4; } service HabrApi { rpc GetKarma(KarmaRequest) returns (KarmaResponse) {} rpc PostArticle(PostArticleRequest) returns (PostArticleResponse) {} }
      
      







grpc \ vsprojects \ Debugフォルダヌに移動し、そこで2぀のコマンドを実行したすずころで、公匏ドキュメントではこの堎所に゚ラヌがあり、匕数が正しくありたせん。

 protoc --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin.exe habr.proto protoc --cpp_out=. habr.proto
      
      





出力では、4぀のファむルを取埗したす。





これは掚枬するのが難しくないので、䞊蚘のプロトコルを䜿甚しおメッセヌゞを亀換できる将来のクラむアントおよびサヌビスのワヌクピヌスです。



プロゞェクトを䜜成したしょう



  1. Visual Studioで新しい゜リュヌションを䜜成し、HabrAPIず呌びたす。
  2. 2぀のコン゜ヌルアプリケヌション、HabrServerずHabrClientを远加したす。
  3. 前の手順で生成されたhおよびssファむルをそれらに远加したす。 4぀すべおをサヌバヌに含める必芁があり、クラむアントにはhabr.pb.hおよびhabr.pb.ccのみが含たれたす。
  4. grpc \ third_party \ protobuf \ srcおよびgrpc \ includeフォルダヌぞのパスを远加フォルダヌの远加のプロゞェクト蚭定に远加したす。
  5. 远加のラむブラリディレクトリのプロゞェクト蚭定でgrpc \ third_party \ protobuf \ cmake \ Debugにパスを远加したす。
  6. 远加の䟝存関係のプロゞェクト蚭定にlibprotobuf.libラむブラリを远加したす
  7. リンクのタむプを、Protobufが䜜成されたのず同じタむプに蚭定したす[コヌド生成]タブの[ランタむムラむブラリ]プロパティ。 この時点で、必芁な構成でProtobufをビルドしなかったこずが刀明する堎合があり、戻っお再構築する必芁がありたす。 私はあちこちで/ MTdを遞択したした。
  8. Nugetを介しおzlibずopensslに䟝存関係を远加したす。




今、すべおが順調に進んでいたす。 確かに、ただ䜕も機胜しおいたせん。



お客様


ここではすべおが簡単です。 たず、habr.pb.hで生成されたスタブから継承されたクラスを䜜成する必芁がありたす。 次に、GetKarmaメ゜ッドずPostArticleメ゜ッドを実装したす。 第䞉に、それらを呌び出しお、たずえば、コン゜ヌルに結果を衚瀺したす。 次のようになりたす。



 #include <iostream> #include <memory> #include <string> #include <grpc/grpc.h> #include <grpc++/channel.h> #include <grpc++/client_context.h> #include <grpc++/create_channel.h> #include <grpc++/credentials.h> #include "habr.grpc.pb.h" using grpc::Channel; using grpc::ChannelArguments; using grpc::ClientContext; using grpc::Status; using HabrahabrApi::KarmaRequest; using HabrahabrApi::KarmaResponse; using HabrahabrApi::PostArticleRequest; using HabrahabrApi::PostArticleResponse; using HabrahabrApi::HabrApi; class HabrahabrClient { public: HabrahabrClient(std::shared_ptr<Channel> channel) : stub_(HabrApi::NewStub(channel)) {} float GetKarma(const std::string& username) { KarmaRequest request; request.set_username(username); KarmaResponse reply; ClientContext context; Status status = stub_->GetKarma(&context, request, &reply); if (status.ok()) { return reply.karma(); } else { return 0; } } bool PostArticle(const std::string& username) { PostArticleRequest request; request.set_title("Article about gRPC"); request.set_body("bla-bla-bla"); request.set_tag("UFO"); request.set_hab("Infopulse"); PostArticleResponse reply; ClientContext context; Status status = stub_->PostArticle(&context, request, &reply); return status.ok() && reply.posted(); } private: std::unique_ptr<HabrApi::Stub> stub_; }; int main(int argc, char** argv) { HabrahabrClient client( grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials(), ChannelArguments())); std::string user("tangro"); std::string reply = client.GetKarma(user); std::cout << "Karma received: " << reply << std::endl; return 0; }
      
      





サヌバヌ


サヌバヌにも同様の話がありたす-habr.grpc.pb.hで生成されたサヌビスクラスから継承し、そのメ゜ッドを実装したす。 次に、特定のポヌトでリスナヌを起動し、顧客を埅ちたす。 このようなもの



 #include <iostream> #include <memory> #include <string> #include <grpc/grpc.h> #include <grpc++/server.h> #include <grpc++/server_builder.h> #include <grpc++/server_context.h> #include <grpc++/server_credentials.h> #include "habr.grpc.pb.h" using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::Status; using HabrahabrApi::KarmaRequest; using HabrahabrApi::KarmaResponse; using HabrahabrApi::PostArticleRequest; using HabrahabrApi::PostArticleResponse; using HabrahabrApi::HabrApi; class HabrahabrServiceImpl final : public HabrApi::Service { Status GetKarma(ServerContext* context, const KarmaRequest* request, KarmaResponse* reply) override { reply->set_karma(42); return Status::OK; } Status PostArticle(ServerContext* context, const PostArticleRequest* request, PostArticleResponse* reply) override { reply->set_posted(true); reply->set_url("some_url"); return Status::OK; } }; void RunServer() { std::string server_address("0.0.0.0:50051"); HabrahabrServiceImpl service; ServerBuilder builder; builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&service); std::unique_ptr<Server> server(builder.BuildAndStart()); std::cout << "Server listening on " << server_address << std::endl; server->Wait(); } int main(int argc, char** argv) { RunServer(); return 0; }
      
      







gRPCを䜿甚しお頑匵っおください。



All Articles