ShowProgramCode

顯示具有 grpc 標籤的文章。 顯示所有文章
顯示具有 grpc 標籤的文章。 顯示所有文章

2022年8月5日 星期五

C# 連結Golang的Grpc Server

Grpc Client專案要如何設定,請參考之前的文章
這裡主要說明的是如何使用C# .NetCore作為Client連結Golang的Grpc Server。

Golang Grpc Server proto調整

syntax = "proto3";  // 定義要使用的 protocol buffer 版本

option csharp_namespace = "GrpcTestApi";

package grpcServer;  // for name space
//option go_package = "./;grpcServer";  // generated code 的 full Go import path

message SumRequest {
  repeated int64 input = 1 [packed=true];
}

message SumResponse {
  int64 result = 1;
}

message RemainderRequest{
  int64 a = 1;
  int64 b = 2;
}

message RemainderResponse {
  int64 result = 1;
}

service grpcService {
  rpc Sum(SumRequest) returns (SumResponse) {};
  rpc Remainder(RemainderRequest) returns (RemainderResponse) {};
}

連線Grpc Client Help物件

public class GrpcServerConnectHelp
{
    private string serverUrl;
    private grpcService.grpcServiceClient client;

    public string ServerUrl { get { return serverUrl; } }

    public GrpcServerConnectHelp()
    {
        Init(System.Configuration.ConfigurationManager.AppSettings.Get("GrpcServerUrl"));
    }

    public void Init(string url = null)
    {
        if (string.IsNullOrEmpty(url))
            return;

        serverUrl = url;
        //.NetCore 3.*版本必須加入此行,否則會錯誤。
        AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
        var channel = GrpcChannel.ForAddress(serverUrl);
        client = new grpcService.grpcServiceClient(channel);
    }

    public string CommonApi(string method, string input)
    {
        string resp = "查無此函式";

        if (method.Equals("Sum"))
        {
            return Sum(input);
        }

        if(method.Equals("Remainder"))
        {
            return Remainder(input);
        }

        return resp;
    }

    private string Sum(string input)
    {
        dynamic dyn = JsonConvert.DeserializeObject(input);
        SumRequest request = new SumRequest();

        foreach(var value in dyn.Input)
        {
            long temp = Convert.ToInt64(value);
            request.Input.Add(temp);
        }
        var reply = client.Sum(request);
        return reply.Result.ToString();
    }

    private string Remainder(string input)
    {
        dynamic dyn = JsonConvert.DeserializeObject(input);
        RemainderRequest request = new RemainderRequest();
        request.A = dyn.A;
        request.B = dyn.B;

        var reply = client.Remainder(request);
        return reply.Result.ToString();
    }
}

AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

重點在於.Net Core 3.*的版本再傳入URL前,必須加入上面的語法,否則會產生錯誤

C# Grpc Server&Client範例

使用Grpc的預設專案,建立一個C#的GrpcServer+Client在同一個專案下。

 所以大致有以下三個動作:

  1. 建立範例Grpc Server專案
  2. 在同一個方案內建立Grpc Client專案
  3. 將共用的.proto檔案copy到Client中
  4. 測試專案

建立Grpc Server

  • 建立Grpc服務專案
  • 設定專案名稱
  • 選擇 .Net Core 3.1版本
  • Server的方案總管畫面
  • 更名Server專案名稱
  • 更改資料夾名稱
  • 編輯方案檔
  • 改寫Server專案路徑
GrpcDemo\Grpc.Server.csproj => Grpc.Server\Grpc.Server.cspro
  • 加入第三方套件參考
Server設定完成,執行沒有問題。

建立Grpc Client

  • 在同一方案中加入新專案(Client)
  • 專案類型選擇主控台
  • 設定專案名稱
  • 同樣選擇 .Net Core 3.1版本
  • 專案建置完成的方案總管截圖
  • 將Proto檔Copy到此
  • 改寫 .proto檔案內容
Server端:改寫option內容
GrpcDemo => Grpc.Server
Server端:加入參考
Client端:改寫option內容
GrpcDemo => Grpc.Client
  • 調整Grpc.Client.csproj
  • 重建方案
  • 修改Client程式碼
static async Task Main(string[] args)
{
await Task.Delay(3000);
using var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
Console.WriteLine("請輸入你的名字...");
string name = Console.ReadLine();
var reply = client.SayHello(new HelloRequest { Name = name });
Console.WriteLine("問候語 : " + reply.Message);
await channel.ShutdownAsync();
Console.WriteLine("按任何一個鍵退出...");
Console.ReadKey();
}
  • 從方案屬性調整起始專案
  • 開始測試
測試成功!!!

2022年7月8日 星期五

goLang grpc 安裝問題proto或protoc-gen-go不是可執行的程式

最近被要求寫一個grpc base的server範例,之後可能需要用到。

基本上範例所有動作都是參考下面網址:

https://pjchender.dev/golang/grpc-getting-started/


但是針對這個網址的說明,對我而言不明確的部分,加上紀錄。以防止下一次需要用到相關功能時,發生相同的問題。

一、 'protoc' 不是內部或外部命令、可執行的程式或批次檔。

首先剛開始時我沒有找到上面的網址,所以我先執行了go get -u google.golang.org/grpc、go get github.com/golang/protobuf/protoc-gen-go。執行go get github.com/golang/protobuf/protoc-gen-go時還發生另一個錯誤,go get github.com/golang/protobuf/protoc-gen-go已經不使用了,要求我改用google.golang.org/protobuf。

然後我照了另外一篇文章的說明,先寫proto檔案,在檔案路徑下執行protoc *.proto --go_out=plugins=grpc:. --go_opt=paths=source_relative,就出現了上面的錯誤: 'protoc' 不是內部或外部命令、可執行的程式或批次檔。

這個比較簡單,因為我沒有安裝protoc,另外最上方網址的文章提供的指令並非window使用的,我參考了下面網址,先解壓縮資料夾後,放入我慣用的路徑,最後在去環境變數中設定PATH,執行protoc --version就正常可以使用了。

https://hoohoo.top/blog/mac-linux-windows-install-protocol-buffer-protobuf-compiler-way/


 二、'protoc-gen-go' 不是內部或外部命令、可執行的程式或批次檔。

這個就比較麻煩了,當protoc安裝完畢,我再次在檔案路徑下執行protoc *.proto --go_out=plugins=grpc:. --go_opt=paths=source_relative,就出現了上面的錯誤:'protoc-gen-go' 不是內部或外部命令、可執行的程式或批次檔。

我花了不少時間查詢,包含改變環境參數中的PATH、GOPATH...,都沒有成功執行指令,最終我查到了下面的網址,將GOPATH下bin的檔案copy一份到GOROOT的bin底下就成功了(汗)@@

https://icode.best/i/35480546158182

但有個地方和上方網址的說明不同,protoc-gen-go.exe檔案有,protoc-gen-go-grpc.exe檔案是沒有的,可能因為我安裝的並非github.com/golang/protobuf/protoc-gen-go版本。

不過目前為止,我的測試範本的Server功能可正常執行,之後如果有問題將再繼續補充。