溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

DotBPE.RPC的示例分析

發(fā)布時間:2021-09-16 17:09:30 來源:億速云 閱讀:142 作者:小新 欄目:編程語言

這篇文章給大家分享的是有關DotBPE.RPC的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

0x00 簡介

DotBPE.RPC是一款基于dotnet core編寫的RPC框架,而它的爸爸DotBPE,目標是實現(xiàn)一個開箱即用的微服務框架,但是它還差點意思,還僅僅在構思和嘗試的階段。但不管怎么說RPC是微服務的基礎,先來講講RPC的實現(xiàn)吧。DotBPE.RPC底層通信默認實現(xiàn)基于DotNetty,這是由微軟Azure團隊開發(fā)的C#的Netty實現(xiàn),非???。當然你也可以替換成其他Socket通信組件。DotBPE.RPC使用的默認協(xié)議名稱叫Amp,編解碼使用谷歌的Protobuf3,不過這些默認實現(xiàn)都是可以替換的。

undefined

0x01 關于Amp協(xié)議和Google Protobuf

Amp(A Message Protocol)

Amp(A Message Protocol) ,中文名叫 一個消息協(xié)議 ,是DotBPE.RPC默認實現(xiàn)的消息協(xié)議,在實際開發(fā)中,其實是不需要了解消息是如何編解碼和傳輸?shù)?,但是了解協(xié)議有助于進一步了解框架。協(xié)議基本結構如下圖所示:

      0        1 2 3 4   5 6 7 8     9     10 11     12 13   <length>-14
+------------+----------+---------+------+-------+---------+------------+
| <ver/argc> | <length> |  <seq>  |<type>|<serId>| <msgid> |   <data>   |
+------------+----------+---------+------+-------+---------+------------+

Amp協(xié)議默認消息頭長為14個字節(jié),不包含擴展包頭
第0位:ver/argc // 為版本號,暫時來說,默認為0
第1-4位: length //為包總長度(含包頭長度)
第5-8位: sequence // 為消息序列號,通過該序列號對應 請求<--->響應
第9位: type // 消息類型,現(xiàn)值有5種,如下:

Request = 1, Response = 2, Notify = 3,NotFound = 4, ERROR = 5
第10-11位: serviceId//消息ID ushort類型
第12-13位: msgId//消息ID ushort類型
在Amp協(xié)議中,serviceId標識一類請求,類似應用中的模塊,而msgId標識模塊中的具體方法

其后緊跟實際的數(shù)據

Google Protobuf

Google Protocol Buffer( 簡稱 Protobuf) 是 Google 公司內部的混合語言數(shù)據標準,目前已經正在使用的有超過 48,162 種報文格式定義和超過 12,183 個 .proto 文件。他們用于 RPC 系統(tǒng)和持續(xù)數(shù)據存儲系統(tǒng)。

Protocol Buffers 是一種輕便高效的結構化數(shù)據存儲格式,可以用于結構化數(shù)據串行化,或者說序列化。它很適合做數(shù)據存儲或 RPC 數(shù)據交換格式??捎糜谕ㄓ崊f(xié)議、數(shù)據存儲等領域的語言無關、平臺無關、可擴展的序列化結構數(shù)據格式。目前提供了 多種語言的API,包括C++、 C# 、GO、 JAVA、 PYTHON

我在之前的博客使用CSharp編寫Google Protobuf插件中有過介紹如果通過編寫插件的方式,來通過定義proto文件,并生成我們需要的代碼。

在DotBPE.RPC 中,我使用protobuf來作為服務的描述文件,并通過自定義的插件方式來生成服務端和客戶端代理類。

0x02 快速開始

0. 前提

因為DotBPE是基于dotnet core開發(fā)的,你本地必須已經有了dotnet core開發(fā)環(huán)境
使用github托管代碼,所以你必須已經安裝了git客戶端
需要通過protoc生成模板代碼,所以你必須已經安裝了google protobuf命令行工具

1. 下載示例程序

為了能夠解釋我們的快速開始程序,你需要一份本地能夠運行的示例代碼。從github上下載我已經寫好的示例代碼,可以讓你快速的搭建程序,免去一些繁瑣,但是又必須的步驟。

>$ # Clone the repository to get the example code:    
>$ git clone https://github.com/xuanye/dotbpe-sample.git  
>$ cd dotbpe-sample

使用VS2017,或者VSCode打開下載好的代碼,目錄結構如下所示:
DotBPE.RPC的示例分析

如果你使用VS2017 可以自動幫你還原,如果使用VSCode的話 ,需要運行dotnet restore 下載依賴,成功后使用dotnet build 編譯一下看看結果:看著很完美
DotBPE.RPC的示例分析

2. 運行程序

運行Server
>$ cd HelloDotBPE.Server   
>$ dotnet run
運行Client
>$ cd HelloDotBPE.Client   
>$ dotnet run

恭喜!已經使用DotBPE.RPC運行一個Server/Client的應用程序。

3. 來一起看一下代碼吧

3.1 服務描述文件proto

首先是DotBPE.RPC框架中對proto的擴展文件,所有的項目都需要這個文件,關于如何擴展proto,我的這篇博客有比較詳細的介紹,這里就不重復說了

//dotbpe_option.proto 文件

syntax = "proto3";
package dotbpe;


option csharp_namespace = "DotBPE.ProtoBuf";

import "google/protobuf/descriptor.proto";

//擴展服務
extend google.protobuf.ServiceOptions {
  int32 service_id = 51001;
  bool disable_generic_service_client = 51003; //禁止生成客戶端代碼
  bool disable_generic_service_server = 51004; //禁止生成服務端代碼
}
extend google.protobuf.MethodOptions {
  int32 message_id = 51002;
}

extend google.protobuf.FileOptions {
  bool disable_generic_services_client = 51003; //禁止生成客戶端代碼
  bool disable_generic_services_server = 51004; //禁止生成服務端代碼
  bool generic_markdown_doc = 51005; //是否生成文檔 本示例中無用
  bool generic_objectfactory = 51006; //是否生成objectfactory 本示例中無用
}

下面的服務描述文件 greeter.proto 才是真正的示例的服務描述文件:比較簡單,定義一個Greeter Rpc服務,并定義一個Hello的方法

//greeter.proto
syntax = "proto3";
package dotbpe;

option csharp_namespace = "HelloDotBPE.Common";

// 引入擴展
import public "dotbpe_option.proto";

// 定義一個服務
service Greeter {
  option (service_id)= 100 ;//消息ID,全局必須唯一
  // Sends a greeting
  rpc Hello (HelloRequest) returns (HelloResponse) {
    option (message_id)= 1 ;//設定消息ID,同一服務內唯一
  }

}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}
// The response message containing the greetings
message HelloResponse {
  string message = 1;
}

通過protoc工具生成模板代碼,示例中的代碼生成到了 HelloDotBPE.Common_g 目錄下,本地可以運行shell命令的同學可以直接到
dotbpe-sample\script\generate 目錄運行sh generate_hello.sh (windows下一般安裝cgywin),不能運行的同學也可以在HelloDotBPE目錄下,直接運行命令行

protoc -I=../protos --csharp_out=./HelloDotBPE.Common/_g/ --dotbpe_out=./HelloDotBPE.Common/_g/   ../protos/dotbpe_option.proto ../protos/greeter.proto  --plugin=protoc-gen-dotbpe=../../tool/protoc_plugin/Protobuf.Gen.exe

當然我還是建議大家安裝以下cgywin運行環(huán)境,可以運行unix上的一些常用命令。同時在部署到正式環(huán)境的時候可以公用開發(fā)環(huán)境的一些腳本。

3.2 服務端代碼

服務實現(xiàn):

// 服務實現(xiàn)代碼
public class GreeterImpl : GreeterBase 
{ 
   public override Task<HelloResponse> HelloAsync(HelloRequest request)
   {
        // 直接返回Hello Name
       return Task.FromResult(new HelloResponse() { Message = "Hello " + request.Name });
   }
}

服務端啟動類

 public class Startup : IStartup
    {
       
        public void Configure(IAppBuilder app, IHostingEnvironment env)
        {
           
        }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddDotBPE(); // 添加DotBPE.RPC的核心依賴
            services.AddServiceActors<AmpMessage>(actors => {
                actors.Add<GreeterImpl>(); // 注冊服務實現(xiàn)
            });

            return services.BuildServiceProvider();
        }
    }

啟動服務端

   class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = System.Text.Encoding.UTF8;

            //在控制臺輸出調試日志
            DotBPE.Rpc.Environment.SetLogger(new DotBPE.Rpc.Logging.ConsoleLogger());

            var host = new RpcHostBuilder()
                .UseServer("0.0.0.0:6201") //綁定本地端口6201
                .UseStartup<Startup>()
                .Build();

            host.StartAsync().Wait();

            Console.WriteLine("Press any key to quit!");
            Console.ReadKey();

            host.ShutdownAsync().Wait();

        }
    }
3.3 客戶端代碼
 class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = Encoding.UTF8;

            var client = AmpClient.Create("127.0.0.1:6201"); //建立鏈接通道
            var greeter = new GreeterClient(client); //客戶端代理類
           
            while (true)
            {
                Console.WriteLine("input your name and press enter:");
                string name = Console.ReadLine();
                if ("bye".Equals(name))
                {
                    break;
                }
                try
                {
                    var request = new HelloRequest() { Name = name };
                    var result = greeter.HelloAsync(request).Result;                  
                    Console.WriteLine($"---------------receive form server:{result.Message}-----------");
                                    
                }
                catch (Exception ex)
                {
                    Console.WriteLine("發(fā)生錯誤:" + ex.Message);
                }
            }
            Console.WriteLine($"---------------close connection-----------");
            client.CloseAsync();
        }
    }

感謝各位的閱讀!關于“DotBPE.RPC的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI