前言
netcore 发布以来,一直很关注netcore的进程。目前在公司负责的网站也历经波折的全部有.net framework 4.0 全部切换到netcore 2.2 版本中。虽然过程遇到的坑不少,但好在最后坚持下来。目前系统全部运行稳定运行在k8s。虽然目前已经用netcore 码了不少业务代码,但总觉得很多新的语言特性、新的api没有使用到,为了学习netcore,决定做造一些简单的轮子,顺便学习下网络编程。
关于Rpc
RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。【百度百科】
实现步骤
-
网络传输
- 使用netcore 新的api System.IO.Pipelines 实现了一个基于TCP传输组件 组件地址
-
序列化、反序列化
- 使用简单的netcore3.0自带的System.Text.Json 实现【只为实现功能,性能可能不行】
-
服务注册与获取
-
使用netcore自带的DI组件Microsoft.Extensions.DependencyInjection
-
服务注册
private static void RegisterIService(Assembly assembly)
{
var serviceCollection = new ServiceCollection();
var classTypes = assembly
.GetTypes()
.Where(type => type.IsClass && type.IsPublic && typeof(IRpcService).IsAssignableFrom(type)); foreach (var classType in classTypes)
{
var interfaceType = classType.GetInterfaces().FirstOrDefault();
serviceCollection.AddSingleton(interfaceType, classType);
Console.WriteLine($"注册服务:{interfaceType.FullName},{classType.Name}");
}
var provider = serviceCollection.BuildServiceProvider(); RpcServiceLocator.Init(provider, assembly);
} -
通过类名获取类型,之后使用GetService获取注册的服务实例
-
-
代理类生成
- 使用 DispatchProxy 动态生成代理类
使用方法
-
服务端
//获取需要注册的服务所在的程序集
var serviceAssembly = Assembly.GetAssembly(typeof(IUserService));
serviceCollection.AddRpcServer(configuration, serviceAssembly);
var serviceProvider = serviceCollection.BuildServiceProvider();
var server = serviceProvider.GetService<RpcServer>();
await server.StartAsync(); -
客户端
var serviceCollection = new ServiceCollection();
var configuration = BuildConfiguration();
serviceCollection.AddLogging(configure => configure.AddConsole());serviceCollection.AddRpcClient(configuration);
var serviceProvider = serviceCollection.BuildServiceProvider();
var client = serviceProvider.GetService<RpcClient>();
await client.StartAsync();var userService = client.CreateProxy<IUserService>();
for (int i = 0; i < 100; i++)
{
var result = userService.GetUserNameById(new TestParam { Id = 1.ToString() });
}