共计 4703 个字符,预计需要花费 12 分钟才能阅读完成。
今天给大家介绍一下基于.NetCore 的 RPC 框架 DotNetCoreRpc 都是怎样的。文章的内容丸趣 TV 小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着丸趣 TV 小编的思路一起来阅读吧。
前言
一直以来对内部服务间使用 RPC 的方式调用都比较赞同, 因为内部间没有这么多限制,最简单明了的方式就是最合适的方式。个人比较喜欢类似 Dubbo 的那种使用方式,采用和本地方法相同的方式,把接口层独立出来作为服务契约,为服务端提供服务,客户端也通过此契约调用服务。.Net 平台上类似 Dubbo 这种相对比较完善的 RPC 框架还是比较少的,GRPC 确实是一款非常优秀的 RPC 框架,能跨语言调用,但是每次还得编写 proto 文件,个人感觉还是比较麻烦的。如今服务拆分,微服务架构比较盛行的潮流下,一个简单实用的 RPC 框架确实可以提升很多开发效率。
简介
随着.Net Core 逐渐成熟稳定,为我一直以来想实现的这个目标提供了便利的方式。于是利用闲暇时间本人手写了一套基于 Asp.Net Core 的 RPC 框架,算是实现了一个自己的小目标。大致的实现方式,Server 端依赖 Asp.Net Core,采用的是中间件的方式拦截处理请求比较方便。Client 端可以是任何可承载.Net Core 的宿主程序。通信方式是 HTTP 协议,使用的是 HttpClientFactory。至于为什么使用 HttpClientFactory,因为 HttpClientFactory 可以更轻松的实现服务发现,而且可以很好的集成 Polly,很方便的实现,超时重试,熔断降级这些,给开发过程中提供了很多便利。由于本人能力有限,基于这些便利,站在巨人的肩膀上,简单的实现了一个 RPC 框架, 项目托管在 GitHub 上 https://github.com/softlgl/DotNetCoreRpc 有兴趣的可以自行查阅。
开发环境
Visual Studio 2019
.Net Standard 2.1
Asp.Net Core 3.1.x
使用方式
打开 Visual Studio 先新建一个 RPC 契约接口层,这里我起的名字叫 IRpcService。然后新建一个 Client 层 (可以是任何可承载.Net Core 的宿主程序) 叫 ClientDemo, 然后建立一个 Server 层 (必须是 Asp.Net Core 项目) 叫 WebDemo, 文末附本文 Demo 连接, 建完这些之后项目结构如下:
Client 端配置 #
Client 端引入 DotNetCoreRpc.Client 包,并引入自定义的契约接口层
PackageReference Include= DotNetCoreRpc.Client
然后可以愉快的编码了,大致编码如下
class Program
static void Main(string[] args)
{ IServiceCollection services = new ServiceCollection();
//* 注册 DotNetCoreRpcClient 核心服务
services.AddDotNetCoreRpcClient()
//* 通信是基于 HTTP 的, 内部使用的 HttpClientFactory, 自行注册即可
.AddHttpClient(WebDemo , client = { client.BaseAddress = new Uri( http://localhost:13285/ });
IServiceProvider serviceProvider = services.BuildServiceProvider();
//* 获取 RpcClient 使用这个类创建具体服务代理对象
RpcClient rpcClient = serviceProvider.GetRequiredService RpcClient
//IPersonService 是我引入的服务包 interface,需要提供 ServiceName, 即 AddHttpClient 的名称
IPersonService personService = rpcClient.CreateClient IPersonService ( WebDemo
PersonDto personDto = new PersonDto
{
Id = 1,
Name = yi 念之间 ,
Address = 中国 ,
BirthDay = new DateTime(2000,12,12),
IsMarried = true,
Tel = 88888888888
};
bool addFlag = personService.Add(personDto);
Console.WriteLine($ 添加结果 =[{addFlag}]
var person = personService.Get(personDto.Id);
Console.WriteLine($ 获取 person 结果 =[{person.ToJson()}]
var persons = personService.GetAll();
Console.WriteLine($ 获取 persons 结果 =[{persons.ToList().ToJson()}]
personService.Delete(person.Id);
Console.WriteLine($ 删除完成
Console.ReadLine();
}
}
到这里 Client 端的代码就编写完成了
Server 端配置 #
Client 端引入 DotNetCoreRpc.Client 包,并引入自定义的契约接口层
PackageReference Include= DotNetCoreRpc.Server Version= 1.0.2 /
然后编写契约接口实现类,比如我的叫 PersonService
// 实现契约接口 IPersonService
public class PersonService:IPersonService
private readonly ConcurrentDictionary int, PersonDto persons = new ConcurrentDictionary int, PersonDto
public bool Add(PersonDto person)
{ return persons.TryAdd(person.Id, person);
}
public void Delete(int id)
{ persons.Remove(id,out PersonDto person);
}
// 自定义 Filter
[CacheFilter(CacheTime = 500)]
public PersonDto Get(int id)
{ return persons.GetValueOrDefault(id);
}
// 自定义 Filter
[CacheFilter(CacheTime = 300)]
public IEnumerable PersonDto GetAll()
{ foreach (var item in persons)
{
yield return item.Value;
}
}
}
通过上面的代码可以看出,我自定义了 Filter,这里的 Filter 并非 Asp.Net Core 框架定义的 Filter,而是 DotNetCoreRpc 框架定义的 Filter, 自定义 Filter 的方式如下
//* 要继承自抽象类 RpcFilterAttribute
public class CacheFilterAttribute: RpcFilterAttribute
public int CacheTime { get; set; }
//* 支持属性注入, 可以是 public 或者 private
//* 这里的 FromServices 并非 Asp.Net Core 命名空间下的, 而是来自 DotNetCoreRpc.Core 命名空间
[FromServices]
private RedisConfigOptions RedisConfig { get; set; }
[FromServices]
public ILogger CacheFilterAttribute Logger { get; set; }
public override async Task InvokeAsync(RpcContext context, RpcRequestDelegate next)
{ Logger.LogInformation($ CacheFilterAttribute Begin,CacheTime=[{CacheTime}], >以上代码基本上完成了对服务端业务代码的操作, 接下来我们来看如何在 Asp.Net Core 中配置使用 DotNetCoreRpc。打开 Startup, 配置如下代码既可
public class Startup
public void ConfigureServices(IServiceCollection services)
{ services.AddSingleton IPersonService, PersonService ()
.AddSingleton(new RedisConfigOptions { Address = 127.0.0.1:6379 , Db = 10 })
//* 注册 DotNetCoreRpcServer
.AddDotNetCoreRpcServer(options = {
//* 确保添加的契约服务接口事先已经被注册到 DI 容器中
// 添加契约接口
//options.AddService IPersonService
// 或添加契约接口名称以 xxx 为结尾的
//options.AddService( *Service
// 或添加具体名称为 xxx 的契约接口
//options.AddService( IPersonService
// 或扫描具体命名空间下的契约接口
options.AddNameSpace( IRpcService
// 可以添加全局过滤器, 实现方式和 CacheFilterAttribute 一致
options.AddFilter LoggerFilterAttribute
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// 这一堆可以不要 +1
if (env.IsDevelopment())
{ app.UseDeveloperExceptionPage();
}
// 添加 DotNetCoreRpc 中间件既可
app.UseDotNetCoreRpc();
// 这一堆可以不要 +2
app.UseRouting();
// 这一堆可以不要 +3
app.UseEndpoints(endpoints =
{
endpoints.MapGet( / , async context =
{
await context.Response.WriteAsync( Server Start!
});
});
}
}
DotNetCoreRpc 都是怎样的相关的内容可以搜索丸趣 TV 之前的文章或者浏览下面的文章进行学习哈!相信丸趣 TV 小编会给大家增添更多知识, 希望大家能够支持一下丸趣 TV!