realtek audio console无法连接rpc服务_.NET Core的RPC框架DotNetCoreRpc

(给DotNet加星标,提升.Net技能)

转自:yi念之间 cnblogs.com/wucy/p/13096515.html

前言

一直以来对内部服务间使用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连接,建完这些之后项目结构如下:

605fbd3d2783e1f36010a3dded75000e.png

Client端配置

Client端引入DotNetCoreRpc.Client包,并引入自定义的契约接口层

<PackageReference Include="DotNetCoreRpc.Client" Version="1.0.2" />

然后可以愉快的编码了,大致编码如下

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();//IPersonService是我引入的服务包interface,需要提供ServiceName,即AddHttpClient的名称
IPersonService personService = rpcClient.CreateClient("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 IEnumerableGetAll(){
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 Logger { get; set; }public override async Task InvokeAsync(RpcContext context, RpcRequestDelegate next){
Logger.LogInformation($"CacheFilterAttribute Begin,CacheTime=[{CacheTime}],Class=[{context.TargetType.FullName}],Method=[{context.Method.Name}],Params=[{JsonConvert.SerializeObject(context.Parameters)}]");await next(context);
Logger.LogInformation($"CacheFilterAttribute End,ReturnValue=[{JsonConvert.SerializeObject(context.ReturnValue)}]");
}
}

以上代码基本上完成了对服务端业务代码的操作,接下来我们来看如何在Asp.Net Core中配置使用DotNetCoreRpc。打开Startup,配置如下代码既可

public class Startup
{
public void ConfigureServices(IServiceCollection services){
services.AddSingleton()
.AddSingleton(new RedisConfigOptions { Address = "127.0.0.1:6379", Db = 10 })//*注册DotNetCoreRpcServer
.AddDotNetCoreRpcServer(options => {//*确保添加的契约服务接口事先已经被注册到DI容器中//添加契约接口//options.AddService();//或添加契约接口名称以xxx为结尾的//options.AddService("*Service");//或添加具体名称为xxx的契约接口//options.AddService("IPersonService");//或扫描具体命名空间下的契约接口
options.AddNameSpace("IRpcService");//可以添加全局过滤器,实现方式和CacheFilterAttribute一致
options.AddFilter();
});
}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){//这一堆可以不要+1if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}//添加DotNetCoreRpc中间件既可
app.UseDotNetCoreRpc();//这一堆可以不要+2
app.UseRouting();//这一堆可以不要+3
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{await context.Response.WriteAsync("Server Start!");
});
});
}
}

以上就是Server端简单的使用和配置,是不是感觉非常的Easy。

附上Demo:https://files.cnblogs.com/files/wucy/DotNetCoreRpcDemo.zip

总结

能自己实现一套RPC框架是我近期以来的一个愿望,现在可以说实现了。虽然看起来没这么高大上,但是整体还是符合RPC的思想。主要还是想自身实地的实践一下,顺便也希望能给大家提供一些简单的思路。

不是说我说得一定是对的,我讲得可能很多是不对的,但是我说的东西都是我自身的体验和思考,也许能给你带来一秒钟、半秒钟的思考,亦或是哪怕你觉得我哪一句话说的有点道理,能引发你内心的感触,这就是我做这件事的意义。

最后,欢迎大家评论区或本项目GitHub(https://github.com/softlgl/DotNetCoreRpc)下批评指导。

- EOF -

5539529cec33480c82f506a5022b0842.png

推荐阅读   点击标题可跳转 .NET Core实战之基于角色的访问控制的设计 C# 9.0 终于来了,您还学的动吗? .NET 5.0 Preview 5 发布

看完本文有收获?请转发分享给更多人

关注「DotNet」加星标,提升.Net技能 

766991c1edf0a9e76ab25863f0a458d0.png

好文章,我在看❤️

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值