入門乾貨之Grpc的.Net實現-MagicOnion

此文章簡單殘暴,學習成本較低,你能夠跟着我一塊兒擼代碼,一塊兒吐槽,一塊兒砸鍵盤。如下操做均爲 core2.0 環境。php

 

0x0一、Grpcjava

 

  一、介紹python

     Google主導開發的RPC框架,使用HTTP/2協議並用ProtoBuf做爲序列化工具,支持多種語言。在.NET Core 「大更新」 以前,也就是目前來講還算是個很不錯的選擇。git

  

  二、吐槽github

      a、有不少性能比較的文章拿Grpc開涮.web

      b、搭建困難,噁心,複雜,反胃,有點吃不消,吃嗎丁啉不必定好使,砸鍵盤也解決不了問題。數據庫

  

  三、搭建流程json

      a、引用緩存

        

        

        都能搜索到,搜索不到就打全。ruby

 

      b、編寫跨語言服務文件(.proto),內容以下

    

syntax = "proto3";
package gRPCDemo;
service gRPC {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

    

      c、這時開始用到了tools, 敲命令:

        首先你的路徑能識別下面兩個exe,若是不能,就搜索這兩個exe,我當時就沒找到,用everthing搜索,而後複製粘貼。

        命令:protoc.exe -I GrpcConsole --csharp_out GrpcConsole GrpcConsole\helloworld.proto --grpc_out GrpcConsole --plugin=protoc-gen-grpc=grpc_csharp_plugin.exe

        對,你找文章都這一長串,demo也是,運行時候各類報錯,神特麼煩,也不跟你細說選項做用,注意事項。

        這裏就詳細說一下:

          ①、 -I 指定一個或者多個目錄,用來搜索.proto文件的。因此上面那行的GrpcConsole\helloworld.proto 已經能夠換成helloworld.proto了,由於-I已經指定了。注意:若是不指定,那就是當前目錄,沒毛病。

          ②、--csharp_out 生成C#代碼,固然了還能cpp_out、java_out、javanano_out、js_out、objc_out、php_out、python_out、ruby_out 這時候你就應該知道,這玩意就是支持多語言的,才用的,生成一些文件,而後給各個語言平臺調用。參數1是輸出路徑,參數2是proto的文件名或者路徑。 

          ③、--grpc_out 到這裏可能有人會懵逼,咋回事?C#不是有一個本身的輸出目錄麼?怎麼又一個輸出?  

            csharp_out是輸出相似於我們平時寫的實體類,接口,定義之類的。生成的文件叫,額,就叫xxx.cs吧.

            grpc_out是跟服務相關,建立,調用,綁定,實現相關。生成的玩意叫xxxGrpc.cs。 對比上個選項生成的文件名,大概能瞭解個十之八九吧。

          ④、--plugin=protoc-gen-grpc=grpc_csharp_plugin.exe 這個就是csharp的插件,python有python的,java有java的。你不指定它,你毛都生成不了。

 

      d、開發

          請容許我作被悲傷、絕望地砸鍵盤動做,你忙活了那麼久,如今剛剛進入開發階段,具體的,本身個去看官方demo.  畢竟本文重點並非這貨。

 

0x0二、MagicOnion

  一、介紹

      首先這裏聲明一點,技術無國界。

      MagicOnion 是一位來自日本的 CTO (目前就任於Grani遊戲公司), UniRx、MsgPack序列化CSharp實現的做者,連續...反正好多年的MVP(從2011年開始),叫Yoshifumi Kawai ?(咋這麼像‘卡哇伊’??)。做品集:https://github.com/neuecc

      MagicOnion是對Grpc的封裝,而且採用了MessagePack序列化技術,提升性能,隨後支持了SwaggerUI。

      MessagePack (msgPack)是很早以前的一個序列化技術,各文章媒體介紹說比json快10倍,以前關注過,json這兩年的勢頭太猛了。 MessagePack-CSharp 去年(2017年)開始浮出水面的,實測比json.net序列化快不少不少,不是一個數量級,這裏我就不談protobuf和mesasgepack的差異了,由於我可能寫了假代碼(他的readme說MessagePack比protobuf效率要高,我測protobuf序列化性能比他要高)。

      Swagger, 必應一大把。

      MIT協議,寫着放心,用着舒心。

 

  二、吐槽

      兩個月沒更新了,Github上有灰。

 

  三、普通C/S框架搭建流程

       a、Nuget上搜MagicOnion,下載安裝。

      b、很是很是重要的接口,你不得不寫的接口,這個接口服務端和客戶端都要定義。

      

 1   //無論你在哪裏寫,反正服務端和客戶端都要寫,對!要麼引用,要麼寫如出一轍的。
 2   //你能看懂的那都是你寫的。
 3   //你看不懂的都是它庫裏自帶的,好比IService,UnaryResult<>。
 4   public interface IHello : IService<IHello>
 5   {
 6     UnaryResult<string> Hello(string name);
 7   }
 8   public interface IWorld : IService<IWorld>
 9   {
10     UnaryResult<string> World(string name);
11   }
12 
15 
16    //無論你在哪寫,反正服務端須要實現,客戶端遠程調用接口的時候走的就是這方法
17     public class HelloServices : ServiceBase<IHello>, IHello
18     {
19         public UnaryResult<string> Hello(string name)
20         {
21             return new UnaryResult<string>($"hello {name}");
22         }
23     }
24     public class WorldServices : ServiceBase<IWorld>, IWorld
25     {
26         public UnaryResult<string> World(string name)
27         {
28             return new UnaryResult<string>($"This is {name}'s world!");
29         }
30     }  

      c、編寫客戶端和服務端,簡單到我很差意思貼代碼,貼圖吧

      

      

      各位老鐵,這代碼能看懂吧?沒毛病。流傳輸去官網下看Readme的例子,也挺容易。

 

  四、集成在Web中,作成接口。

      a、引用

        MagicOnion.HttpGateway (其中包含了MagicOnion、Asp.net core 中間件擴展、Json.net、MagicOnion.HttpGetway)

        Swashbuckle.AspNetCore

       b、有了第3個C/S的基礎,那麼你就能夠繼續幹了。寫你的接口,而且配上註釋,由於Swagger要用!

        ReturnResult是我本身定義的返回值,跟這些庫無關,你隨便寫。

        

      c、寫你的代碼,實體類,要支持MessagePack序列化,打個標籤。

        

      d、其餘的工做(都隨你便)

        

      

    public class Test :ServiceBase<ITest>, ITest
    {
        public UnaryResult<ReturnResult> GetStudent(int sid)
        {
            //GetStudentBySidFromDatabase(sid)
            //GetModel
            Student student;
            student.Name = "Test_小明";
            student.Sid = sid;

            //FillResult
            ReturnResult result = new ReturnResult() {
                Data = student,
                Status = 0
            };

            //Return
            return UnaryResult(result);
        }
    }

        這是是實現你定義的接口,你想返回啥都行,讀數據庫,讀緩存都隨便你,我就是簡單寫個例子。

      e、而後就是添加服務,你這個rpc是做爲服務集成在web中的。

      

        public void ConfigureServices(IServiceCollection services)
        {
            //這代碼跟我們以前定義服務的那個代碼一個樣子
            var service = MagicOnionEngine.BuildServerServiceDefinition(new MagicOnionOptions(true)
            {
                MagicOnionLogger = new MagicOnionLogToGrpcLogger()
            });
            var server = new Server
            {
                Services = { service },
                Ports = { new ServerPort("localhost", 8800, ServerCredentials.Insecure) }
            };

            //這裏開始不一樣,你要把註釋生成到xml裏給swagger,這裏是swagger的用法,看不懂去學swagger
            services.AddSwaggerGen(c =>
            {
                var filePath = Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "Swagger.xml");
                c.IncludeXmlComments(filePath);
            });

            server.Start();

            //這裏添加服務
            services.Add(new ServiceDescriptor(typeof(MagicOnionServiceDefinition), service));
            services.AddMvc();
        }

      f、配置,各類配置。

     public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            //獲取添加了的服務
            var magicOnion = app.ApplicationServices.GetService<MagicOnionServiceDefinition>();
            //使用MagicOnion的Swagger擴展,就是讓你的rpc接口也能在swagger頁面上顯示
            //下面這些東西你可能乍一看就懵逼,但你看到頁面的時候就會發現,一個蘿蔔一個坑。
            //注意:swagger原生用法屬性都是大寫的,這裏是小寫。
            app.UseMagicOnionSwagger(magicOnion.MethodHandlers, new SwaggerOptions("MagicOnion.Server", "Swagger Integration Test", "/")
            {
                
                 Info = new Info()
                 {
                     title = "MGrpc",
                     version = "v1",
                     description = "This is the API-Interface for MGrpc",
                     termsOfService = "By NMS",
                     contact = new Contact
                     {

                         name = "LanX",
                         email = "2765968624@qq.com"
                     }
                 },
                //使用Swagger生成的xml,就是你接口的註釋
                XmlDocumentPath = PlatformServices.Default.Application.ApplicationBasePath + "Swagger.xml"
            });
            //要想讓rpc成爲該web服務的接口,流量和協議被統一到你寫的這個web項目中來,那麼就要用個方法連接你和rpc
            //這個web項目承接你的請求,而後web去調用rpc獲取結果,再返回給你。
            //所以須要下面這句話
            app.UseMagicOnionHttpGateway(magicOnion.MethodHandlers, new Channel("localhost:8800", ChannelCredentials.Insecure));
            
  
       if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } //如下是swagger的用法,不贅述 app.UseSwagger(c => { c.RouteTemplate = "swagger/{documentName}/swagger.json"; }); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "API-v1"); c.ShowJsonEditor(); c.ShowRequestHeaders(); }); app.UseSwagger(); app.UseMvc(); }

   五、成果:


      

 

0x0三、窺視你的通訊過程

    一、抓包查看它們的通訊過程,裝Wireshark, 可是它不抓本地包,只抓網卡的,本地環回地址其實是走的是操做系統內部,跟網卡無關,所以須要藉助一個工具,Npcap,下載頁面https://nmap.org/npcap/#download,文章中間有下載的地方。某些人會留意到神器Nmap,吊得一比。裝完以後你的Wireshark會多一個接口,本地接口,而後你就偵聽吧,過濾語句:http || tcp.port == 8800,複製粘貼就是幹。

  效果:

     
      
      
      交互過程以及三次握爪
      
      發送數據,可靠傳輸
      

0x0四、廣告時間
    

0x0五、結束
     
     

    
感謝各位老鐵能堅持看完,沒有彩蛋,拜拜~[轉載請註明出處]
相關文章
相關標籤/搜索