.Net Core gRpc调用

这篇具有很好参考价值的文章主要介绍了.Net Core gRpc调用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录
  • 简介
  • 创建gRPC
    • 创建服务端
    • 创建控制台测试
    • 创建自定义服务
  • 服务器流式处理方法
    • custom.proto
    • CustomGreeterService.cs
    • gRpcRequest.cs
  • 客户端流式处理方法
    • custom.proto
    • CustomGreeterService.cs
    • gRpcRequest.cs
  • 双向流式处理方法
    • custom.proto
    • CustomGreeterService.cs
    • gRpcRequest.cs
  • .Net Core 调用gRpc
    • 项目引用
    • Program.cs
    • gRpcController.cs
    • 支持Aop
      • 服务端 Program.cs
      • 服务端 LogInterceptor.cs
      • 客户端 Program.cs
      • 客户端 LogInterceptor.cs
  • jwt+gRPC验证
    • 准备Jwt Token发布中心
      • Program.cs
      • JwtConfig.cs
      • AuthenorizationController.cs
      • JwtHeleper.cs
      • RoleInfo.cs
      • UserInfo.cs
      • appsetting.json
    • gRPC准备
      • Program.cs
      • CustomGreeterService.cs
      • JwtAuthorization.cs
    • 客户端调用
      • Program.cs
      • HttpClientHelper.cs
      • gRpcController.cs
  • Rpc 与 Restful 区别

简介

  • 高性能、开源的通用 RPC 框架

  • 实现不同语言相互调用

  • 官网

  • Protobuf 消息参考

  • proto3 语言指南

  • 创建服务

  • 微软gRpc 概述

创建gRPC

创建服务端

  1. vs2022直接搜索grpc默认下一步创建

创建控制台测试

  1. 创建控制台
  2. 引入以下dll
<PackageReference Include="Google.Protobuf" Version="3.23.4" />
<PackageReference Include="Grpc.Net.Client" Version="2.55.0" />
<PackageReference Include="Grpc.Tools" Version="2.56.2">
  1. 打开服务端.csproj文件,复制以下内容粘贴到客户端的.csproj文件中并修改GrpcServices=Client,客户端.csproj文件出现 None Update="Protos\greet.proto" 这组ItemGroup是可以删除的
<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>

4.将服务端Protos文件夹及内容全部拷贝到客户端项目下
5.在客户端创建gRpcRequest.cs文件并增加下列代码,端口号填写服务端端口

using Grpc.Net.Client;
using GrpcService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static GrpcService.Greeter;

namespace gRpcConsoleTest
{
    public static class gRpcRequest
    {
        public static async Task SayHello()
        {
            using(var channel = GrpcChannel.ForAddress("https://localhost:7166")) 
            {
                GreeterClient client = new GreeterClient(channel);
                HelloReply reply = await client.SayHelloAsync(new HelloRequest() {Name = "jjjjj" });
                Console.WriteLine(reply.Message);
            }
        }
    }
}

6.客户端Program.cs文件中加入测试代码 await gRpcRequest.SayHello();
7.服务端和客户端在想要调试的位置打上断点
8.运行服务端
9.选中客户端项目右键 -> 调试 -> 启动新实例 即可两个项目全部命中断点进行调试测试

创建自定义服务

  • 服务端

    1. Protos文件夹添加 custom.proto文件并添加下列代码,重新生成项目打开项目所在文件夹,打开路径:obj\Debug\net6.0\Protos 查看CustomGrpc.cs是否存在,如果没有存在则在.csproj文件中添加:

    syntax = "proto3";
    
    option csharp_namespace = "Custom.Service";
    
    package custom;
    
    service CustomGreeter {
      rpc Plus(Number) returns (NumberResult) ;
    }
    
    message Number {
        int32 leftNumber = 1;
        int32 rightNumber = 2;
    }  
    
    message NumberResult{
        int32 result = 1;
    }
    
    1. Services文件夹下添加CustomGreeterService.cs文件,namespace 与 .protos中的csharp_namespace对应
    using Grpc.Core;
    
    namespace Custom.Service
    {
        public class CustomGreeterService : CustomGreeter.CustomGreeterBase
        {
            public override async Task<NumberResult> Plus(Number request, ServerCallContext context) => 
                await Task.FromResult<NumberResult>(new NumberResult()
                {
                    Result = request.LeftNumber + request.RightNumber,
                });
        }
    }
    

    3.在Program.cs 中注册新创建的服务,加入下列代码:
    app.MapGrpcService();

  • 客户端

    1. 将服务端的custom.proto文件拷贝到Protos文件夹内并在.csproj文件中添加(注意这里GrpcServices="Client"):

    2. 重新生成项目并检查路径: obj\Debug\net6.0\Protos 是否生成对应的CustomGrpc.cs文件
    3. 加入测试代码:
    public static async Task Plus(int leftNumber,int rightNumber)
    {
        using (var channel = GrpcChannel.ForAddress("https://localhost:7166"))
        {
            CustomGreeterClient client = new CustomGreeterClient(channel);
            NumberResult number = await client.PlusAsync(new Custom.Service.Number() { LeftNumber = leftNumber,RightNumber = rightNumber});
            Console.WriteLine(number.Result);
        }
    }
    
    1. 测试步骤与上面控制台测试一样,调试方式也一样

服务器流式处理方法

custom.proto

syntax = "proto3";

option csharp_namespace = "Custom.Service";

package custom;

service CustomGreeter {
  rpc SelfIncreaseServer(IntArrayModel) returns (stream BathTheCatResp); //服务端流
}

message BathTheCatResp{
    string message = 1;
}

message IntArrayModel{
    repeated int32 number = 1;
}

CustomGreeterService.cs

using Grpc.Core;

namespace Custom.Service
{
    public class CustomGreeterService : CustomGreeter.CustomGreeterBase
    {
        public override async Task SelfIncreaseServer(IntArrayModel request, IServerStreamWriter<BathTheCatResp> responseStream, ServerCallContext context)
        {
            foreach (var item in request.Number)
            {
                Console.WriteLine($"客户端传入参数: {item}");
                await responseStream.WriteAsync(new BathTheCatResp() { Message = item.ToString()});
                await Task.Delay(1000);
            }
        }
    }
}

gRpcRequest.cs

using Custom.Service;
using Grpc.Core;
using Grpc.Net.Client;
using GrpcService;
using static Custom.Service.CustomGreeter;

namespace gRpcConsoleTest
{
    public static class gRpcRequest
    {
        public static async Task SelfIncreaseServe()
        {
            using (var channel = GrpcChannel.ForAddress("https://localhost:7166"))
            {
                CustomGreeterClient client = new CustomGreeterClient(channel);
                IntArrayModel intArray = new IntArrayModel();
                for (int i = 0; i < 10; i++)
                {
                    intArray.Number.Add(i);   
                }

                var batch = client.SelfIncreaseServer(intArray);

                Task batchTask = Task.Run(async ()=>
                {
                    await foreach (var item in batch.ResponseStream.ReadAllAsync())
                    {
                        Console.WriteLine($"服务端相应数据: {item.Message}");
                    }
                });

                await batchTask;
            }
        }
    }
}

客户端流式处理方法

custom.proto

syntax = "proto3";

option csharp_namespace = "Custom.Service";

package custom;

service CustomGreeter {
  rpc SelfIncreaseClient(stream BathTheCatReq) returns (IntArrayModel); //客户端流
}

message BathTheCatResp{
    string message = 1;
}

message IntArrayModel{
    repeated int32 number = 1;
}

CustomGreeterService.cs

using Grpc.Core;

namespace Custom.Service
{
    public class CustomGreeterService : CustomGreeter.CustomGreeterBase
    {
        public override async Task<IntArrayModel> SelfIncreaseClient(IAsyncStreamReader<BathTheCatReq> requestStream, ServerCallContext context)
        {
            IntArrayModel result = new IntArrayModel();
            while (await requestStream.MoveNext())
            {
                var message = requestStream.Current;  
                Console.WriteLine($"客户端流传入消息: {message}");
                result.Number.Add(message.Id + 1);
            }
            return result;
        }
    }
}

gRpcRequest.cs

using Custom.Service;
using Grpc.Core;
using Grpc.Net.Client;
using GrpcService;
using static Custom.Service.CustomGreeter;

namespace gRpcConsoleTest
{
    public static class gRpcRequest
    {
        public static async Task SelfIncreaseClient()
        {
            using (var channel = GrpcChannel.ForAddress("https://localhost:7166"))
            {
                CustomGreeterClient client = new CustomGreeterClient(channel);
                var batch = client.SelfIncreaseClient();
                for (int i = 0; i < 10; i++)
                {
                    await batch.RequestStream.WriteAsync(new BathTheCatReq() { Id = i });
                    await Task.Delay(1000);
                }
                await batch.RequestStream.CompleteAsync();

                foreach (var item in batch.ResponseAsync.Result.Number)
                {
                    Console.WriteLine($"响应数据: {item}");
                }
            }
        }
    }
}

双向流式处理方法

custom.proto

syntax = "proto3";

option csharp_namespace = "Custom.Service";

package custom;

service CustomGreeter {
  rpc SelfIncreaseDouble(stream BathTheCatReq) returns (stream BathTheCatResp);//双端流
}

message BathTheCatReq{
    int32 id = 1;
}

message BathTheCatResp{
    string message = 1;
}

CustomGreeterService.cs

using Grpc.Core;

namespace Custom.Service
{
    public class CustomGreeterService : CustomGreeter.CustomGreeterBase
    {
        public override async Task SelfIncreaseDouble(IAsyncStreamReader<BathTheCatReq> requestStream, IServerStreamWriter<BathTheCatResp> responseStream, ServerCallContext context)
        {
            while (await requestStream.MoveNext())
            {
                var message = requestStream.Current.Id;
                Console.WriteLine($"客户端流传入消息: {message}");
                await responseStream.WriteAsync(new BathTheCatResp() { Message=(message+1).ToString()});
            }
        }
    }
}

gRpcRequest.cs

using Custom.Service;
using Grpc.Core;
using Grpc.Net.Client;
using GrpcService;
using static Custom.Service.CustomGreeter;
using static GrpcService.Greeter;

namespace gRpcConsoleTest
{
    public static class gRpcRequest
    {
        public static async Task SelfIncreaseDouble()
        {
            using (var channel = GrpcChannel.ForAddress("https://localhost:7166"))
            {
                CustomGreeterClient client = new CustomGreeterClient(channel);
                var batch = client.SelfIncreaseDouble();

                Task batchTask = Task.Run(async () =>
                {
                    await foreach (var item in batch.ResponseStream.ReadAllAsync())
                    {
                        Console.WriteLine($"服务端相应数据: {item.Message}");
                    }
                });


                for (int i = 0; i < 10; i++)
                {
                    await batch.RequestStream.WriteAsync(new BathTheCatReq() { Id = i });
                    await Task.Delay(1000);
                }

                await batchTask;
            }
        }
    }
}

.Net Core 调用gRpc

项目引用

<PackageReference Include="Google.Protobuf" Version="3.24.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.55.0" />
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.55.0" />
<PackageReference Include="Grpc.Tools" Version="2.56.2">

<ItemGroup>
  <Protobuf Include="Protos\custom.proto" GrpcServices="Client" />
  <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>

Program.cs

//CustomGreeterClient grpc连接类
builder.Services.AddGrpcClient<CustomGreeterClient>(options =>
{
    options.Address = new Uri("https://localhost:7166"); //grpc 服务地址
});

gRpcController.cs

using Custom.Service;
using Microsoft.AspNetCore.Mvc;
using static Custom.Service.CustomGreeter;

namespace gRpcWebAPI.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class gRpcController : ControllerBase
    {
        CustomGreeterClient _client; //使用构造函数注入
        public gRpcController(CustomGreeterClient client)
        {
            _client = client;
        }

        [HttpGet]
        public async Task<IActionResult> Plus(int leftNumber, int rightNumber)
        {
            NumberResult number = await _client.PlusAsync(new Custom.Service.Number() { LeftNumber = leftNumber, RightNumber = rightNumber });
            return new JsonResult(number);
        }
    }
}

支持Aop

  1. 服务端, 客户端 都需要继承 Interceptor
  2. 重新需要实现Aop的方法,如服务端: UnaryServerHandler,客户端: AsyncUnaryCall 针对一元调用的Aop
  3. 我这里使用的是NLog写的日志,NLog可以使用可以翻阅我先前的博客
    .Net Core NLog+oracel

服务端 Program.cs

builder.Services.AddGrpc(options =>
{
    options.Interceptors.Add<LogInterceptor>();
});

服务端 LogInterceptor.cs

using Grpc.Core;
using Grpc.Core.Interceptors;

namespace GrpcService.Interceptors
{
    public class LogInterceptor : Interceptor
    {
        ILogger<LogInterceptor> _logger;
        public LogInterceptor(ILogger<LogInterceptor> logger)
        {
            _logger = logger;
        }
        public override Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)
        {
            _logger.LogInformation("===========UnaryServerHandler==========");
            return continuation(request, context);
        }
    }
}

客户端 Program.cs

builder.Services.AddGrpcClient<CustomGreeterClient>(options =>
{
    options.Address = new Uri("https://localhost:7166"); //服务端地址
}).AddInterceptor<LogInterceptor>();

客户端 LogInterceptor.cs

using Grpc.Core;
using Grpc.Core.Interceptors;
namespace GrpcService.Interceptors
{
    public class LogInterceptor : Interceptor
    {
        ILogger<LogInterceptor> _logger;
        public LogInterceptor(ILogger<LogInterceptor> logger)
        {
            _logger = logger;
        }
        public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
        {
            _logger.LogInformation("===========AsyncUnaryCall===========");
            return continuation(request, context);
        }
    }
}

jwt+gRPC验证

  1. 准备单独的一个网站发布jwt Token (授权中心)
  2. 然后在gRPC项目中jwt鉴权 和 获取到角色信息之后授权
  3. webapi测试gRPC调用, 先在授权中心获取token然后在 ConfigureChannel 方法中设置gRPC全局的jwt token
  4. 返回401: jwt鉴权不通过
  5. 返回403: jwt授权不通过

准备Jwt Token发布中心

Program.cs

//读取Jwt配置
builder.Services.Configure<JwtConfig>(builder.Configuration.GetSection("JwtTokenOptions"));

JwtConfig.cs

namespace AuthenorizationCenter.Tools.Model
{
    public class JwtConfig
    {
        public string? Audience { get; set; }
        public string? Issuer { get; set; }
        public string? SecurityKey { get; set; }
        public int ExpiresMinutes { get; set; }
    }
}

AuthenorizationController.cs

using AuthenorizationCenter.Tools;
using AuthenorizationCenter.Tools.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;

namespace AuthenorizationCenter.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AuthenorizationController : ControllerBase
    {

        JwtConfig _jwtconfig;
        public AuthenorizationController(IOptions<JwtConfig> jwtconfig) 
        {
            _jwtconfig = jwtconfig.Value;
        }

        [HttpGet]
        public async Task<string> GetToken(string userName, string passWord)
        {
            string token = JwtHeleper.GetToken(new()
            {
                UserName = userName,
                Extended1 = "无信息",
                Role = new List<RoleInfo>()
                {
                    new RoleInfo() { Id = "1",Role="系统管理员"} ,
                    new RoleInfo() { Id = "2",Role="用户管理员"} ,
                }
            }, new()
            {
                Audience = _jwtconfig.Audience,
                Issuer = _jwtconfig.Issuer,
                SecurityKey = _jwtconfig.SecurityKey,
                ExpiresMinutes = 5,
            });

            await Task.CompletedTask;
            return token;
        }
    }
}

JwtHeleper.cs

using AuthenorizationCenter.Tools.Model;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace AuthenorizationCenter.Tools
{
    public class JwtHeleper
    {
        public static string GetToken(UserInfo user, JwtConfig jwtConfig)
        {
            List<Claim> claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, user.UserName ?? ""),
                new Claim("Extended1", user.Extended1 ?? ""),
                new Claim("Extended2", user.Extended2 ?? ""),
                new Claim("Extended3", user.Extended3 ?? ""),
                new Claim("Extended4", user.Extended4 ?? ""),
                new Claim("Extended5", user.Extended5 ?? ""),
            };
            if (user.Role is not null)
            {
                foreach (var item in user.Role)
                {
                    claims.Add(new Claim(item.Id.ToString(), item.Role));
                }
            }
            if (jwtConfig.SecurityKey == null)
            {
                throw new Exception("JwtConfig.SecurityKey 不能为空");
            }
            SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SecurityKey));
            SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            JwtSecurityToken token = new JwtSecurityToken(
                issuer: jwtConfig.Issuer,
                audience: jwtConfig.Audience,
                claims: claims,
                expires: DateTime.UtcNow.AddMinutes(jwtConfig.ExpiresMinutes),
                signingCredentials: creds
            );
            string resultToken = new JwtSecurityTokenHandler().WriteToken(token);
            return resultToken;
        }
    }
}

RoleInfo.cs

namespace AuthenorizationCenter.Tools.Model
{
    public class RoleInfo
    {
        public string Id { get; set; }
        public string Role { get; set; }
    }
}

UserInfo.cs

namespace AuthenorizationCenter.Tools.Model
{
    public class UserInfo
    {
        public string? UserName { get; set; }
        public List<RoleInfo>? Role { get; set; }
        public string? Extended1 { get; set; }
        public string? Extended2 { get; set; }
        public string? Extended3 { get; set; }
        public string? Extended4 { get; set; }
        public string? Extended5 { get; set; }
    }
}

appsetting.json

{
  "JwtTokenOptions": {
    "Issuer": "https://localhost:7117",
    "Audience": "https://localhost:7117",
    "SecurityKey": "kq4DY5N1eFJhscOkI7Zp4Nd0WNy9d9AEsN6Yjgdv9OxLyol66tzGBKT_7vwolN7GZ8EDwqJBwccjDJfb81ws5s3sbbP5wUzQ3-PcTSsD-Rueiu2rsOUZwg_NR3RBCwmtouV-832YV2trCjNTawLB1z0LMukWGFNaAJVZ8WdQcrYn6a0ko5oVhZqaHBgsCLEGiqPtoFsiCcrJTz1IvXHk9_cDSr2hwEmSl18GlkOtgCHFH8aidYth3aQHRHuClTi6Y9mYRJtqqK-FNQYq4ZP23DSGZGFejJFTnM9YMpppuTMLklhSGySwX8rfjZ_0L5ac18nHaykTaiC2fvH00W42qQ"
  }
}

gRPC准备

Program.cs

JwtConfig jwtConfig = new JwtConfig();
builder.Configuration.Bind("JwtTokenOptions", jwtConfig);

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters()
    {
        ValidateIssuer = true,
        ValidIssuer = jwtConfig.Issuer, //发行人
        ValidateAudience = true,
        ValidAudience = jwtConfig.Audience,//订阅人
        ValidateIssuerSigningKey = true,
        //对称加密密钥
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SecurityKey!)),
        ValidateLifetime = true, //验证失效时间
        ClockSkew = TimeSpan.FromSeconds(30), //过期时间容错值
        RequireExpirationTime = true,
        AudienceValidator = (audiences, securityToken, validationParameters) =>
        {
            return true;
        },
        LifetimeValidator = (notBefore, expires, securityToken, validationParameters) =>
        {
            return true;
        }
    };
});

builder.Services.AddTransient<IUserServices, UserServices>();
builder.Services.AddTransient<IAuthorizationHandler, JwtAuthorization>();
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("JwtPolicy", policy =>
    {
        //jwt 授权
        policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
        //这里为自定义授权指定一下类
        .AddRequirements(new UserRoleRequirement(JwtBearerDefaults.AuthenticationScheme));
    });
});

CustomGreeterService.cs

using Grpc.Core;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;

namespace Custom.Service
{
    public class CustomGreeterService : CustomGreeter.CustomGreeterBase
    {
        [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme,Policy = "JwtPolicy")]
        public override async Task<NumberResult> Plus(Number request, ServerCallContext context) => 
            await Task.FromResult<NumberResult>(new NumberResult()
            {
                Result = request.LeftNumber + request.RightNumber,
            });
    }
}

JwtAuthorization.cs

using Cnpc.Com.Ioc.IBll;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;

namespace GrpcService.Authorization
{
    public class UserRoleRequirement : IAuthorizationRequirement
    {
        public string AuthenticateScheme;
        public UserRoleRequirement(string authenticateScheme)
        {
            AuthenticateScheme = authenticateScheme;
        }
    }
    public class JwtAuthorization : AuthorizationHandler<UserRoleRequirement>
    {
        IUserServices userSercices;
        public JwtAuthorization(IUserServices userSercices)
        {
            this.userSercices = userSercices;
        }
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserRoleRequirement requirement)
        {
            string? userName = context.User.FindFirst(it => it.Type == ClaimTypes.Name)?.Value;
            if (userSercices.IsAdmin(userName!))
            {
                context.Succeed(requirement);
            }
            else
            {
                context.Fail();
            }
            return Task.CompletedTask;
        }
    }
}

客户端调用

Program.cs

builder.Services.AddGrpcClient<CustomGreeterClient>(options =>
{
    options.Address = new Uri("https://localhost:7166");
}).AddInterceptor<LogInterceptor>().ConfigureChannel(async config =>
{
    //所有调用自动添加 Authorization
    CallCredentials credentials = CallCredentials.FromInterceptor(async (context, metadata) =>
    {
        string token = await HttpClientHelper.HttpGetAsync("https://localhost:7117/api/Authenorization?userName=admin&passWord=666");
        metadata.Add("Authorization", $"Bearer {token}");
    });
    config.Credentials = ChannelCredentials.Create(new SslCredentials(), credentials);
});

HttpClientHelper.cs

using Newtonsoft.Json;
using System.Text;

namespace gRpcWebAPI.Utility
{
    public static class HttpClientHelper
    {
        public static async Task<string> HttpGetAsync(string url, string contentType = "application/json", Dictionary<string, string> headers = null)
        {
            using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient())
            {
                if (contentType != null)
                    client.DefaultRequestHeaders.Add("ContentType", contentType);
                if (headers != null)
                {
                    foreach (var header in headers)
                        client.DefaultRequestHeaders.Add(header.Key, header.Value);
                }
                HttpResponseMessage response = await client.GetAsync(url);
                return await response.Content.ReadAsStringAsync();
            }
        }
    }
}

gRpcController.cs

using Custom.Service;
using Grpc.Core;
using gRpcWebAPI.Utility;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System.Security.Cryptography.X509Certificates;
using static Custom.Service.CustomGreeter;

namespace gRpcWebAPI.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class gRpcController : ControllerBase
    {
        CustomGreeterClient _client;
        public gRpcController(CustomGreeterClient client)
        {
            _client = client;
        }

        [HttpGet]
        public async Task<IActionResult> AsyncPlus(int leftNumber, int rightNumber)
        {
            try
            {
                //string token = await HttpClientHelper.HttpGetAsync("https://localhost:7117/api/Authenorization?userName=admin&passWord=666");
                //Metadata jwtCode = new Metadata { { "Authorization", $"Bearer {token}" } };
                NumberResult number = await _client.PlusAsync(new Custom.Service.Number() { LeftNumber = leftNumber, RightNumber = rightNumber });
                return new JsonResult(number);
            }
            catch (Exception ex)
            {
                return new JsonResult(ex.Message);
            }
        }

        [HttpGet]
        public IActionResult Plus(int leftNumber, int rightNumber)
        {
            try
            {
                string token = HttpClientHelper.HttpGet("https://localhost:7117/api/Authenorization?userName=admin&passWord=666");

                Metadata jwtCode = new Metadata { { "Authorization",$"Bearer {token}"} };
                NumberResult number = _client.Plus(new Custom.Service.Number() { LeftNumber = leftNumber, RightNumber = rightNumber },headers: jwtCode);
                return new JsonResult(number);
            }
            catch (Exception ex)
            {
                return new JsonResult(ex.Message);
            }
        }
    }
}

Rpc 与 Restful 区别

  • RPC是以一种调用本地方法的思路来调用远程方法,通过各种RPC框架隐藏调用远程方法的细节,让用户以为调用的就是本地方法。RPC隐藏了底层网络通信的复杂度,让我们更专注于业务逻辑的开发。

  • REST通过HTTP实现,把用户的需求抽象成对资源的操作,用户必须通过HTTP协议的GET、HEAD、POST、PUT、DELETE、TRACE、OPTIONS七种基本操作去和服务器交互。

  • RPC通常是服务器和服务器之间的通信,比如和中间件的通信,MQ、分布式缓存、分布式数据库等等。

  • 而REST通常是面向客户端的(一般是浏览器),他们的使用场景也是不一样的。文章来源地址https://www.toymoban.com/news/detail-635828.html

到了这里,关于.Net Core gRpc调用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • .NET Core 实现日志打印输出在控制台应用程序中

    在本文中,我们将探讨如何在 .NET Core 应用程序中将日志消息输出到控制台,从而更好地了解应用程序的运行状况。 在 .NET Core 中,日志输出打印是使用 Microsoft.Extensions.Logging 命名空间中的类和方法实现的。首先,我们需要确保在项目中添加了以下必要的依赖包: Microsoft.Ex

    2024年02月11日
    浏览(144)
  • 【服务器】ASP.Net Core(C#)创建Web站点

    简单几步实现本地ASP.Net.Core web 站点结合cpolar内网穿透工具实现远程访问 1. 创建站点 *环境搭建,这边测试,使用.NET 6.0 SDK,可以点击跳转到官网下载,下载后安装即可. 安装完成后,进入到某个文件夹,打开powershell执行下面命令,创建新的 Web 应用,名称叫:aspnetcoreapp 2. 运行站点 信任开

    2024年02月11日
    浏览(47)
  • Taurus .Net Core 微服务开源框架:Admin 插件【4-7】 - 配置管理-Mvc【Plugin-Metric 接口调用次数统计】

    继上篇:Taurus .Net Core 微服务开源框架:Admin 插件【4-6】 - 配置管理-Mvc【Plugin-Doc 接口测试及文档】 本篇继续介绍下一个内容: 配置界面如下: 打开开关时,可以通过访问Metric菜单查看统计项:   默认不统计。 如果为true,则写入硬盘。 时间单位为秒。  配置的是相对路径

    2024年02月04日
    浏览(57)
  • .NET Core 简介

         微软于2016年推出了新一代的开发平台,并且将其命名为.NET Core。相较于旧的.NET Framework。 .NET Core有如下优点:    1).NET Core采用模块化开发。不再像.NET Framework那样需要安装整个安装包。.NET Core核心只包含很少的文件,所有其他模块都需要单独安装。根据需要引用各自

    2024年03月26日
    浏览(35)
  • .net core中如何自定义静态文件目录、默认主页、和文件浏览目录?

    在.NET Core中,UseStaticFiles、UseDefaultFiles、UseDirectoryBrowser和UseFileServer中间件用于处理静态文件和目录浏览。下面我将为你提供一个简单的例子,演示它们的用法。 首先,确保你的项目已经安装了 Microsoft.AspNetCore.StaticFiles  NuGet包,因为这是这些中间件的依赖。 然后,打开  S

    2024年02月04日
    浏览(39)
  • .net core中Grpc使用报错:The remote certificate is invalid according to the validation procedure.

    因为Grpc采用HTTP/2作为通信协议,默认采用LTS/SSL加密方式传输,比如使用.net core启动一个 服务端(被调用方) 时:   其中使用UseHttps方法添加证书和秘钥。 但是,有时候,比如开发阶段,我们可能没有证书,或者是一个自己制作的临时测试证书,那么在 客户端(调用方)

    2023年04月13日
    浏览(47)
  • .net core 生成项目时.json配置文件没有复制到输出目录

    在程序运行时默认加载.exe文件同文件夹下的配置文件,而不是项目中的.json配置文件,所以需要把.json配置文件设置到自动生成目录,即下图所示:

    2023年04月13日
    浏览(55)
  • [golang 微服务] 4. gRPC介绍,Protobuf结合gRPC 创建微服务

    gRPC是一个 高性能 、 开源 和 通用 的 RPC 框架 , 面向移动端 和 HTTP/2 设计,目前提供 C、Java 和 Go语言版本,分别是:grpc, grpc-java, grpc-go, 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持 (1).提供几乎所有主流语言的实现, 打破语言隔阂 (2). 基于 HTTP/2 标准设计

    2024年02月04日
    浏览(45)
  • 【gRPC实现java端调用go的服务】

    在lib下面的存在一个simple.proto文件,我们使用插件protobuf-maven-plugin对其进行编译。配置如下: 利用插件进行编译 后可以获得对应的文件。 在client下创建一个grpc的包,并将以上两个文件放入。最后创建一个SimpleClient。 最后在Application中调用即可

    2024年02月04日
    浏览(55)
  • 仿`gRPC`功能实现像调用本地方法一样调用其他服务器方法

    在介绍 gRPC 简介之前我们先了解一写概念: 单体架构 单体架构简单理解就是所有的业务代码都在一台服务器上,一旦某个服务宕机,会引起整个应用不可用,隔离性差。只能整体应用进行伸缩,例如整体打包部署一台或多台服务器,浪费资源,可伸缩性差。代码耦合在一起

    2024年02月09日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包