基於C#的GRPC

gRPC(gRPC Remote Procedure Call)是由Google開發的高性能、跨語言的遠程過程調用框架。它基於HTTP/2協議進行通信,支持多種編程語言,包括C++, C#, Java, Python等,使不同語言的應用程序可以通過遠程調用相互通信。

1.關鍵特點和用途:
高性能:gRPC採用了HTTP/2協議,具有低延遲、高吞吐量和複用連接的特點。這使得它非常適合於需要高性能通信的應用程序。
跨語言支持:gRPC支持多種編程語言,允許不同語言的應用程序之間進行跨語言通信。這使得它在微服務架構中非常有用,因爲不同的服務可以使用不同的編程語言實現。
IDL(Interface Definition Language):gRPC使用ProtoBuf(Protocol Buffers)作爲IDL,允許您定義服務接口和消息類型。這提供了強類型的通信,使得通信更加清晰和高效。
多種通信類型:gRPC支持不同類型的通信,包括請求-響應、服務器流、客戶端流和雙向流。這允許您選擇最適合您應用程序需求的通信方式。
自動化代碼生成:通過ProtoBuf定義服務接口和消息類型,gRPC工具會自動生成客戶端和服務器端的代碼,這樣可以大大減少開發工作量。
認證和安全:gRPC支持各種認證和安全機制,包括SSL/TLS,OAuth等,以確保通信的安全性。
服務發現:gRPC可以與服務發現工具(如Consul、etcd)集成,從而實現動態服務發現和負載均衡。
可擴展性:gRPC是一個可擴展的框架,支持各種自定義擴展和中間件。
2.GRPC思路
Grpc類似於一種協議,遵循網絡通訊,以.proto文件爲協議模板進行客戶端與服務端的交互開發,不限制客戶端和服務端的代碼語言風格.也可以在服務端與客戶端使用不同的語言開發

3.編寫.proto文件

 

// Protocol Buffers 語法版本 proto3 版本
syntax = "proto3";
// 定義了消息類型和服務的包名,類似於命名空間,用於避免命名衝突。
package Calculator;
// 定義了一個 gRPC 服務。在大括號中,您可以列出服務方法的定義。
service CalculatorService 
{
    // 定義了一個服務方法。rpc 表示定義一個遠程過程調用(RPC)方法。MyMethod 是方法的名稱,MyRequest 是輸入參數類型,MyResponse 是輸出參數類型。
    rpc MyMethod (MyRequest) returns (MyResponse);

  // 服務器流式方法
  rpc ServerStreamingMethod(Request1) returns (stream Response1);

  // 客戶端流式方法
  rpc ClientStreamingMethod(stream Request2) returns (Response2);

  // 雙向流式方法
  rpc BidirectionalStreamingMethod(stream Request3) returns (stream Response3);
}
message MyRequest 
{
    repeated int32 num = 10;
}
message MyResponse 
{
    repeated string strs = 10;
}

message Request1
{
    string Message = 1;
}
message Response1
{
    string Message = 1;
}
message Request2
{
    string Message = 1;
}
message Response2
{
    string Message = 1;
}
message Request3
{
    string Message = 1;
}
message Response3
{
    string Message = 1;
}
syntax = "proto3";

package Calculator;

import "Protos/Calculator.proto";

service FirstService {
    rpc MyMethod (MyRequest1) returns (MyResponse);
}
message MyRequest1 
{
    repeated int32 num = 10;
}

多個.proto文件間是可以調用的

 

4.添加.proto文件生成的文件編寫服務端和客戶端代碼

.proto文件生成的文件位置 添加到客戶端和服務端

5.服務端代碼

using Calculator;
using Grpc.Core;

class CalculatorServiceImpl : CalculatorService.CalculatorServiceBase
{
    /// <summary>
    /// 發佈響應
    /// </summary>
    /// <param name="request"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public override async Task<MyResponse> MyMethod(MyRequest request, ServerCallContext context)
    {
        MyResponse myResponse = new MyResponse();
        foreach (int i in request.Num)
        {
            myResponse.Strs.Add(i.ToString());
        }
        return myResponse;
    }

    /// <summary>
    /// 服務器流(Server Streaming)
    /// </summary>
    /// <param name="request"></param>
    /// <param name="responseStream"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public override async Task ServerStreamingMethod(Request1 request, IServerStreamWriter<Response1> responseStream, ServerCallContext context)
    {
        for (int i = 0; i < 10; i++)
        {
            Response1 response = new Response1 { Message = request.Message + $"Message {i}" };
            await responseStream.WriteAsync(response);
            await Task.Delay(500); // 模擬每秒發送一次數據
        }
    }

    /// <summary>
    /// 客戶端流(Client Streaming)
    /// </summary>
    /// <param name="requestStream"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public override async Task<Response2> ClientStreamingMethod(IAsyncStreamReader<Request2> requestStream, ServerCallContext context)
    {
        string str = "";
        while (requestStream.MoveNext().Result)
        {
            str += requestStream.Current.Message;
            Console.WriteLine(requestStream.Current.Message);
        }
        return new Response2 { Message = str };
    }
    /// <summary>
    /// 雙向流(Bidirectional Streaming)
    /// </summary>
    /// <param name="requestStream"></param>
    /// <param name="responseStream"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public override async Task BidirectionalStreamingMethod(IAsyncStreamReader<Request3> requestStream, IServerStreamWriter<Response3> responseStream, ServerCallContext context)
    {
        while (requestStream.MoveNext().Result)
        {
            // 處理客戶端發送的請求
            Console.WriteLine(requestStream.Current.Message);
            Response3 response = new Response3 { Message = requestStream.Current.Message + "abc" };
            await responseStream.WriteAsync(response); // 發送響應
            await Task.Delay(500);
        }
    }

}

class Program
{
    static void Main(string[] args)
    {
        const int Port = 50051;

        Server server = new Server
        {
            Services = { CalculatorService.BindService(new CalculatorServiceImpl()) },
            Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }
        };

        server.Start();

        Console.WriteLine("Calculator server listening on port " + Port);
        Console.WriteLine("Press any key to stop the server...");
        Console.ReadKey();

        server.ShutdownAsync().Wait();
    }
}

 

6.客戶端代碼

using Calculator;
using Grpc.Core;

class Program
{
    const string ServerAddress = "localhost";
    const int Port = 50051;
    static void Main(string[] args)
    {
        MyMethod();
        ServerStreamingMethod();
        SelfIncreaseClient();
        BidirectionalStreamingMethod();

        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    }
    /// <summary>
    /// 發佈響應
    /// </summary>
    private static void MyMethod()
    {
        Channel channel = new Channel($"{ServerAddress}:{Port}", ChannelCredentials.Insecure);
        var client = new CalculatorService.CalculatorServiceClient(channel);
        MyRequest myRequest = new MyRequest { Num = { 1, 2, 3, 4 } };
        MyResponse myResponse = client.MyMethod(myRequest);
        Console.WriteLine($"Result: {myResponse.Strs}");
        channel.ShutdownAsync().Wait();
    }

    /// <summary>
    /// 服務器流(Server Streaming)
    /// </summary>
    private static void ServerStreamingMethod()
    {
        Channel channel = new Channel($"{ServerAddress}:{Port}", ChannelCredentials.Insecure);
        var client = new CalculatorService.CalculatorServiceClient(channel);
        Request1 request1 = new Request1 { Message = "ceshi" };
        AsyncServerStreamingCall<Response1> response1s = client.ServerStreamingMethod(request1);
        while (response1s.ResponseStream.MoveNext().Result)
        {
            Console.WriteLine(response1s.ResponseStream.Current.Message);
        }
        channel.ShutdownAsync().Wait();
    }

    /// <summary>
    /// 客戶端流(Client Streaming)
    /// </summary>
    private static async void SelfIncreaseClient()
    {
        Channel channel = new Channel($"{ServerAddress}:{Port}", ChannelCredentials.Insecure);
        var client = new CalculatorService.CalculatorServiceClient(channel);
        var call = client.SelfIncreaseClient();
        for (int i = 0; i < 10; i++)
        {
            await call.RequestStream.WriteAsync(new Request2() { Message = $"第{i}個" });
            await Task.Delay(500);
        }
        await call.RequestStream.CompleteAsync();
        Console.WriteLine($"Result: {call.ResponseAsync.Result.Message}");
        channel.ShutdownAsync().Wait();
    }
    /// <summary>
    /// 雙向流(Bidirectional Streaming)
    /// </summary>
    private static async void BidirectionalStreamingMethod()
    {
        Channel channel = new Channel($"{ServerAddress}:{Port}", ChannelCredentials.Insecure);
        var client = new CalculatorService.CalculatorServiceClient(channel);
        var call = client.BidirectionalStreamingMethod();
        for (int i = 1; i <= 5; i++)
        {
            // 發送請求
            await call.RequestStream.WriteAsync(new Request3 { Message = i.ToString() }); 
            await Task.Delay(500);
        }
        await call.RequestStream.CompleteAsync();

        while (call.ResponseStream.MoveNext().Result)
        {
            // 處理服務器發送的響應
            Console.WriteLine(call.ResponseStream.Current.Message);
        }
        channel.ShutdownAsync().Wait();
    }
}

7.Demo示例

 

 

 

原文鏈接:https://blog.csdn.net/qq1084517825/article/details/134272985

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章