ASP .NET Core 6.0使用Grpc配置服务和调用服务

前言,全文干货,需要知道和理解Grpc的基础上操作,全文仅记录代码过程,有疑问请留言!

一、创建Grpc服务

1、创建Grpc服务应用程序(PS:如何创建我就不细说了,不会的童鞋去看别的教程吧。)

 

2、编写Protos文件和服务

(1)在项目中创建文件夹Protos

(2)并创建文件Teacher.proto

可以理解为我们普通的Csharp代码的Interface接口,IService,用于编写服务接口

 (3)依赖项中,分别添加Nugget程序包

(4)在项目中右键依赖性->管理连接的服务,并且配置grpc的服务teacher为服务器,这样就Protos文件就配置好了

 (5)在项目中创建文件夹Services

(6)Service文件内容

        定义了静态数据List<TeacherInfo> 方便测试和讲解,实际情况中会通过注入IRepository的方式来进行获取数据。

using Google.Protobuf.WellKnownTypes;
using Grpc.Core;

namespace GrpcService.Services
{
    public class TeacherService : Teacher.TeacherBase
    {
        private readonly ILogger<TeacherService> _logger;


        private static readonly List<TeacherInfo> _teacherInfos = new List<TeacherInfo>()
        {
            new TeacherInfo() { Id = "1", Name = "张三", Card = "zs", DeptId = "1", DeptName = "信息部" },
            new TeacherInfo() { Id = "2", Name = "李四", Card = "ls", DeptId = "1", DeptName = "信息部" },
            new TeacherInfo() { Id = "3", Name = "王五", Card = "ww", DeptId = "2", DeptName = "政治部" }
        };

        public TeacherService(ILogger<TeacherService> logger)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }


        public override Task<TeacherInfoResult> GetById(TeacherId request, ServerCallContext context)
        {
            _logger.LogInformation(context.RequestHeaders.GetValue("Authorization"));
            var teacherInfo = _teacherInfos.FirstOrDefault(p => p.Id == request.Id);
            var result = new TeacherInfoResult()
            {
                TeacherId = teacherInfo.Id,
                TeacherCard = teacherInfo.Card,
                TeacherName = teacherInfo.Name,
                DepartmentId = teacherInfo.DeptId,
                DepartmentName = teacherInfo.DeptName
            };

            return Task.FromResult(result);
        }

        public override Task<TeacherInfoResult> GetByToken(Empty request, ServerCallContext context)
        {

            var userId = context.RequestHeaders.GetValue("UserId");
            var teacherInfo = _teacherInfos.FirstOrDefault(p => p.Id == userId);
            var result = new TeacherInfoResult()
            {
                TeacherId = teacherInfo.Id,
                TeacherCard = teacherInfo.Card,
                TeacherName = teacherInfo.Name,
                DepartmentId = teacherInfo.DeptId,
                DepartmentName = teacherInfo.DeptName
            };

            return Task.FromResult(result);
        }

    }

    public record TeacherInfo 
    { 
        public string Id { get; set; }
        public string Name { get; set; }
        public string Card { get; set; }
        public string DeptId { get; set; }
        public string DeptName { get; set; }
    }
}

3、注入文件

通过builder.Services.AddGrpc(); 添加服务

通过app.MapGrpcService<TeacherService>(); 配置服务

这样并搭建好了服务

 

二、配置Grpc客户端

1、创建ASC .NET Core Web API服务(PS:相信研究Grpc的小伙计们这么简单的操作还是会的,不过多余的讲解了)。

2、配置Grpc客户端

(1)依赖项中,分别添加Nugget程序包

(2)Copy写好的Protos文件,并修改为Teacher服务为客户端

直接复制,前面写好Teacher.Protos文件到Client中使用,实际项目开发中也是复制粘贴!

 

(3)Program中添加自定义服务类builder.Services.AddGrapcServiceConfiguration(builder.Configuration);

源码如下

 public static class GrpcServiceExtensions
    {
        public static void AddGrapcServiceConfiguration(this IServiceCollection services, IConfiguration configuration)
        {

            services.AddGrpcClient<Teacher.TeacherClient>(options =>
            {
                options.Address = new Uri(configuration.GetValue<string>("GrpcUrls:FindTeacher"));
            });

        }


    }

(4)appsetings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "GrpcUrls": {
    "FindTeacher": "https://localhost:7108"
  }
}

3、Controller中编写

 [Route("api/[controller]/[action]")]
    [ApiController]
    public class GrpcTeacherController : ControllerBase
    {
        private readonly Teacher.TeacherClient _client;

        public GrpcTeacherController(Teacher.TeacherClient client)
        {
            _client = client ?? throw new ArgumentNullException(nameof(client));
        }

        [HttpGet]
        public async Task<ActionResult> GetTeacher()
        {
            var reply = await _client.GetByIdAsync(new TeacherId { Id = "1" });
            return Ok(reply);
        }

        [HttpGet]
        public async Task<ActionResult> GetTeacherByToken()
        {
            //var authorization = _httpContextAccessor?.HttpContext?.Request.Headers["Authorization"];
            var headers = new Metadata { { "UserId", "1" } };
            var reply = await _client.GetByTokenAsync(request: new Empty(), headers);
            return Ok(reply);
        }
    }

4、调用结果

 

三、配置统一配置JWT鉴权Token

public class AuthInterceptor : Interceptor
    {
        private readonly ILogger<AuthInterceptor> _logger;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public AuthInterceptor(ILogger<AuthInterceptor> logger, IHttpContextAccessor httpContextAccessor)
        {
            _logger = logger;
            _httpContextAccessor = httpContextAccessor;
        }

        public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(
            TRequest request,
             ClientInterceptorContext<TRequest, TResponse> context,
            AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
        {
            var authorization = _httpContextAccessor?.HttpContext?.Request?.Headers["Authorization"].ToString();
            var token = string.IsNullOrEmpty(authorization) ? "" : authorization.Remove(0, 7);

            var metadata = new Metadata
            {
                { "Authorization", $"Bearer {token}" }
            };

            var newContext = new ClientInterceptorContext<TRequest, TResponse>(
                    context.Method,
                    context.Host,
                    context.Options.WithHeaders(
                        (context.Options.Headers ?? new Metadata()).Aggregate(
                            metadata,
                            AddIfNonExistent))
                );

            return continuation(request, newContext);
        }

        private static Metadata AddIfNonExistent(Metadata metadata, Metadata.Entry entry)
        {
            if (metadata.Get(entry.Key) == null) metadata.Add(entry);
            return metadata;
        }
    }
public static class GrpcServiceExtensions
    {
        public static void AddGrapcServiceConfiguration(this IServiceCollection services, IConfiguration configuration)
        {
            services.AddTransient<AuthInterceptor>();

            services.AddGrpcClient<Teacher.TeacherClient>(options =>
            {
                options.Address = new Uri(configuration.GetValue<string>("GrpcUrls:FindTeacher"));
            }).AddInterceptor<AuthInterceptor>();

        }
    }

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值