共計 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!