.NET 微服務(wù):gRPC

對于這個話題,我相信大家很容易想到,HTTP 接口的方式可以解決。

大概的做法類似這樣:

  1. 根據(jù) HTTP 接口需要的參數(shù),將參數(shù)序列化成 json 字符串;

  2. 根據(jù)當(dāng)前項目開發(fā)語言,封裝一個處理 Post||Get 請求的方法,發(fā)送請求;

  3. 接口返回結(jié)果,然后反序列化成實體在邏輯代碼中使用;


可能在單個項目內(nèi)使用這樣的方式痛點并不是很明顯。但如果是在多個項目內(nèi),每個項目都依賴于這個接口,那為了獲取到數(shù)據(jù)可能會寫很多重復(fù)代碼。而且可能因為沒有統(tǒng)一的反序列實體來映射,會出現(xiàn)A項目對這個屬性名反序列化后叫西門慶,到了B項目同樣的屬性名就叫成了武大郎,這樣開發(fā)的同學(xué)也會覺得很不開心。

我們目前的情況是多個項目,而且項目也不是統(tǒng)一的語言。為了解決上面的問題,我們決定使用 gRPC 的方式來處理,基本需要滿足以下條件:

  1. 微服務(wù)化
  2. 跨語言
  3. 性能
  4. 調(diào)用者方便

因為我目前參與的項目基于 .NET 開發(fā),所以下面的一些例子可能會不自覺偏向 C#。


在使用 gRPC 之前,需要先了解一下 RPC、HTTP 接口

RPC
  • RPC(Remote Procedure Call Protocol)就是從一臺機(jī)器(客戶端)上通過參數(shù)傳遞的方式調(diào)用另一臺機(jī)器(服務(wù)器)上的一個函數(shù)或方法并得到返回的結(jié)果,流程如下:
RPC流程
HTTP 接口
  • 論復(fù)雜度,RPC 框架肯定是高于簡單的 HTTP 接口的;

  • HTTP 接口由于受限于 HTTP 協(xié)議,需要帶 HTTP 請求頭,導(dǎo)致傳輸起來效率不如 RPC;

  • RPC 是長鏈接,不必每次通信都要像 HTTP 一樣去握手。

gRPC
  • gRPC 是一個高性能 RPC 框架,和 HTTP 一樣都是一種對 RPC 的實現(xiàn),但性能相比之下更好;

  • 使用 Protocol Buffers 來作為序列化和反序列化,以及接口定義語言,Protocol Buffers 已經(jīng)被證明是非常高效序列化框架;

  • 跨語言,跨平臺,gRPC 支持多種平臺和多種語言;

  • 基于 HTTP/2。


gRPC 服務(wù)創(chuàng)建大概流程如下:

1、創(chuàng)建 .proto 文件,定義通信的數(shù)據(jù)結(jié)構(gòu)和服務(wù)接口。文件內(nèi)包含方法、請求參數(shù)、返回結(jié)果等;

syntax = "proto3";

package MD.CacheService;

service MDCache {
  // 獲取單賬號信息
  rpc GetAccountInfo (AccountInfoRequest) returns (AccountInfoResponse) {}
}

// 獲取單賬號數(shù)據(jù)請求參數(shù)
message AccountInfoRequest {
  // 賬號id
  string accountId = 1;
}

// 獲取單個賬號數(shù)據(jù)返回值
message AccountInfoResponse {
  // 賬號實體
  AccountInfo accountInfo = 1;
}

// 賬號實體
message AccountInfo{
  // 賬號id
  string accountId = 1;
  // 姓名
  string fullname = 2;
  // 頭像
  string avatar = 3;
  // 賬號創(chuàng)建時間,時間戳
  int64 createTime = 4;
}

2、根據(jù) .proto 文件通過 Protocol Buffer 編譯器分別生成服務(wù)隊和客戶端的代碼(看官方的支持,可以選擇一種你最擅長的語言,服務(wù)端和客戶端完全不需要規(guī)定一樣的語言);

生成的代碼

3、基于生成的代碼創(chuàng)建服務(wù)端和客戶端應(yīng)用;

4、在服務(wù)端創(chuàng)建一個類對服務(wù)接口進(jìn)行 override;

public class CacheServiceImpl : MDCache.MDCacheBase
{
  /// <summary>
  /// 獲取單個賬號accountInfo
  /// </summary>
  /// <param name="request"></param>
  /// <param name="context"></param>
  /// <returns></returns>
  public override Task<AccountInfoResponse> GetAccountInfo(AccountInfoRequest request, ServerCallContext context)
  {
    var response = new AccountInfoResponse();

    if (!string.IsNullOrEmpty(request.AccountId))
    {
        response.AccountInfo = GetServiceAccountInfo(request.AccountId);
    }
    return Task.FromResult(response);
  }
}

5、啟動服務(wù)(服務(wù)安裝基于 Topshelf);

class Program
{
  static void Main(string[] args)
  {
    HostFactory.Run(x =>
    {
      x.Service<CacheService>(s =>
      {
          s.ConstructUsing(name => new CacheService());
          s.WhenStarted(tc => tc.Start());
          s.WhenStopped(tc => tc.Stop());
      });
      x.RunAsLocalSystem();
      
      x.SetDisplayName("MD.CacheService");
      x.SetServiceName("MD.CacheService");
    });
  }
}

public class CacheService
{
  private readonly string host = ConfigurationManager.AppSettings["Host"];//服務(wù)IP
  private readonly string port = ConfigurationManager.AppSettings["Port"];//服務(wù)端口

  readonly Server server;
  public CacheService()
  {
    server = new Server
    {
      Services = { MDCache.BindService(new CacheServiceImpl()) },
      Ports = { 
        new ServerPort(host, Convert.ToInt32(port), ServerCredentials.Insecure) 
      }
    };
  }
  public void Start() { server.Start(); }
  public void Stop() { server.ShutdownAsync(); }
}

6、客戶端連接測試

var channel = new Channel("host:port", ChannelCredentials.Insecure);
var client = new MDCacheClient(channel);

C#官方 example ,照著做也可以實現(xiàn)效果

部署:

  • 基于.NET Core 的可以將服務(wù)部署在Linux上;
  • 基于.NET Framework 的可以部署成 Windows 服務(wù),關(guān)于 Windows 服務(wù)方式,這里推薦使用Topshelf,非常簡單。

服務(wù)部署后涉及到負(fù)載和高可用的問題,單點故障是不能接收的。關(guān)于這部分的實現(xiàn)方式,相信熟悉 Nginx 的同學(xué)可以很快解決,當(dāng)然也可以使用其他方案。

參考鏈接:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容