基于.NET CORE微服务框架 -surging的介绍和简单示例 (开源)
一、前言
至今为止编程开发已经11个年头,从 VB6.0,ASP时代到ASP.NET再到MVC, 从中见证了.NET技术发展,从无畏无知的懵懂少年,到现在的中年大叔,从中的酸甜苦辣也只有本人自知。随着岁月的成长,技术也从原来的三层设计到现在的领域驱动设计,从原来的关系型数据库SQL 2000到现在的NOSQL (mongodb,couchbase,redis),从原来基于SOAP协议的web service到现在基于restful 协议的web api,wcf,再到现在rpc微服务。技术的成长也带来岁月的痕迹。
现在微软又出了.NET CORE,为了紧跟微软的步伐,研究了将近1年,从中看了不少开源代码,如NetEscapades.Configuration,eShopOnContainers,rabbit.RPC等等,从中学到了不少知识,后面利用所学加上自己的想法,开发出分布式微服务框架surging。开源地址:点击打开链接。下面会以三篇文章的形式介绍
surging
1.基于.NET CORE微服务框架 -surging的介绍和简单示例 (开源)
2.剥析surging的架构思想
3.后续surging的架构完善工作
二、什么是surging
surging从中文译义来说,冲击,汹涌,也可以翻译成风起云涌。我所希望的是.net core 能成为最流行的技术。
surging从技术层面来说就是基于RPC协议的分布式微服务技术框架,框架依赖于Netty 进行异步通信,采用Zookeeper作为服务注册中心,集成了哈希,随机和轮询作为负载均衡算法
1.服务化应用基本框架
框架的执行过程如下:
1.服务提供者启动,根据RPC协议通过配置的IP和port绑定到netty上
2.注册服务信息存储至Zookeeper
3.客户端CreateProxy调用服务时,从内存中拿到上次通知的所有效的服务地址,根据路由信息和负载均衡机制选择最终调用的服务地址,发起调用
2.简单示例
创建IModuleServices
IUserService.cs:
[ServiceBundle] //服务标记
public interface IUserService
{
Task<string> GetUserName(int id); Task<bool> Exists(int id); Task<int> GetUserId(string userName); Task<DateTime> GetUserLastSignInTime(int id); Task<UserModel> GetUser(int id); Task<bool> Update(int id, UserModel model); Task<IDictionary<string, string>> GetDictionary(); Task TryThrowException();
}
创建领域对象
UserModel:
[ProtoContract]
public class UserModel
{
[ProtoMember(1)]
public string Name { get; set; } [ProtoMember(2)]
public int Age { get; set; }
}
AssemblyInfo.cs,扩展AssemblyModuleType来标识模块,根据AssemblyModuleType进行相关规则的反射注册
[assembly: AssemblyTitle("Surging.IModuleServices.Common")]
[assembly: AssemblyDescription("业务模块接口")]
[assembly: AssemblyModuleType(ModuleType.InterFaceService)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("2103624d-2bc2-4164-9aa5-1408daed9dee")]
创建Domain Service
PersonService.cs
[ModuleName("Person")] //标识实例化名称
public class PersonService : ServiceBase,IUserService
{
#region Implementation of IUserService
private readonly UserRepository _repository;
public PersonService(UserRepository repository)
{
this._repository = repository;
}
public Task<string> GetUserName(int id)
{
return GetService<IUserService>("User").GetUserName(id);
}
public Task<bool> Exists(int id)
{
return Task.FromResult(true);
}
public Task<int> GetUserId(string userName)
{
return Task.FromResult(1);
}
public Task<DateTime> GetUserLastSignInTime(int id)
{
return Task.FromResult(DateTime.Now);
}
public Task<UserModel> GetUser(int id)
{
return Task.FromResult(new UserModel
{
Name = "fanly",
Age = 18
});
}
public Task<bool> Update(int id, UserModel model)
{
return Task.FromResult(true);
}
public Task<IDictionary<string, string>> GetDictionary()
{
return Task.FromResult<IDictionary<string, string>>(new Dictionary<string, string> { { "key", "value" } });
}
public async Task Try()
{
Console.WriteLine("start");
await Task.Delay(5000);
Console.WriteLine("end");
}
public Task TryThrowException()
{
throw new Exception("用户Id非法!");
}
#endregion Implementation of IUserService
}
}
UserService.cs
[ModuleName("User")]//标识实例化名称
public class UserService: IUserService
{
#region Implementation of IUserService
private readonly UserRepository _repository;
public UserService(UserRepository repository)
{
this._repository = repository;
}
public Task<string> GetUserName(int id)
{
return Task.FromResult($"id:{id} is name fanly.");
}
public Task<bool> Exists(int id)
{
return Task.FromResult(true);
}
public Task<int> GetUserId(string userName)
{
return Task.FromResult(1);
}
public Task<DateTime> GetUserLastSignInTime(int id)
{
return Task.FromResult(DateTime.Now);
}
public Task<UserModel> GetUser(int id)
{
return Task.FromResult(new UserModel
{
Name = "fanly",
Age = 18
});
}
public Task<bool> Update(int id, UserModel model)
{
return Task.FromResult(true);
}
public Task<IDictionary<string, string>> GetDictionary()
{
return Task.FromResult<IDictionary<string, string>>(new Dictionary<string, string> { { "key", "value" } });
}
public async Task Try()
{
Console.WriteLine("start");
await Task.Delay(5000);
Console.WriteLine("end");
}
public Task TryThrowException()
{
throw new Exception("用户Id非法!");
}
#endregion Implementation of IUserService
}
}
AssemblyInfo.cs,扩展AssemblyModuleType来标识模块,根据AssemblyModuleType进行相关规则的反射注册
[ModuleName("User")]//标识实例化名称
public class UserService: IUserService
{
#region Implementation of IUserService
private readonly UserRepository _repository;
public UserService(UserRepository repository)
{
this._repository = repository;
}
public Task<string> GetUserName(int id)
{
return Task.FromResult($"id:{id} is name fanly.");
}
public Task<bool> Exists(int id)
{
return Task.FromResult(true);
}
public Task<int> GetUserId(string userName)
{
return Task.FromResult(1);
}
public Task<DateTime> GetUserLastSignInTime(int id)
{
return Task.FromResult(DateTime.Now);
}
public Task<UserModel> GetUser(int id)
{
return Task.FromResult(new UserModel
{
Name = "fanly",
Age = 18
});
}
public Task<bool> Update(int id, UserModel model)
{
return Task.FromResult(true);
}
public Task<IDictionary<string, string>> GetDictionary()
{
return Task.FromResult<IDictionary<string, string>>(new Dictionary<string, string> { { "key", "value" } });
}
public async Task Try()
{
Console.WriteLine("start");
await Task.Delay(5000);
Console.WriteLine("end");
}
public Task TryThrowException()
{
throw new Exception("用户Id非法!");
}
#endregion Implementation of IUserService
}
}
3.服务端
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Surging.Core.Caching.Configurations;
using Surging.Core.CPlatform;
using Surging.Core.CPlatform.Runtime.Server;
using Surging.Core.DotNetty;
using Surging.Core.ProxyGenerator.Utilitys;
using Surging.Core.System.Ioc;
using Surging.Core.Zookeeper;
using Surging.Core.Zookeeper.Configurations;
using System;
using System.Net;
using System.Text;
using System.Threading.Tasks; namespace Surging.Services.Server
{
public class Program
{
static void Main(string[] args)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var services = new ServiceCollection();
var builder = new ContainerBuilder();
ConfigureLogging(services);
builder.Populate(services);
ConfigureService(builder);
ServiceLocator.Current = builder.Build();
ConfigureCache();
ServiceLocator.GetService<ILoggerFactory>()
.AddConsole((c, l) => (int)l >= 3);
StartService();
Console.ReadLine();
} /// <summary>
/// 配置相关服务
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
private static void ConfigureService(ContainerBuilder builder)
{
builder.Initialize();
builder.RegisterServices();
builder.RegisterRepositories();
builder.RegisterModules();
builder.AddCoreServce()
.AddServiceRuntime()
.UseSharedFileRouteManager("c:\\routes.txt")//配置本地路由文件路径
.UseDotNettyTransport()//配置Netty
.UseZooKeeperRouteManager(new ConfigInfo("192.168.1.6:2181",
"/dotnet/unitTest/serviceRoutes"));//配置ZooKeeper
builder.Register(p => new CPlatformContainer(ServiceLocator.Current));
} /// <summary>
/// 配置日志服务
/// </summary>
/// <param name="services"></param>
public static void ConfigureLogging(IServiceCollection services)
{
services.AddLogging();
} /// <summary>
/// 配置缓存服务
/// </summary>
public static void ConfigureCache()
{
new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddCacheFile("cacheSettings.json", optional: false);
} /// <summary>
/// 启动服务
/// </summary>
public static void StartService()
{
var serviceHost = ServiceLocator.GetService<IServiceHost>();
Task.Factory.StartNew(async () =>
{
await serviceHost.StartAsync(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 98));
Console.WriteLine($"服务端启动成功,{DateTime.Now}。");
}).Wait();
}
}
}
4.客户端
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Surging.Core.CPlatform;
using Surging.Core.DotNetty;
using Surging.Core.ProxyGenerator;
using Surging.Core.ProxyGenerator.Utilitys;
using Surging.Core.System.Ioc;
using System.Text; namespace Surging.Services.Client
{
public class Program
{
static void Main(string[] args)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var services = new ServiceCollection();
var builder = new ContainerBuilder();
ConfigureLogging(services);
builder.Populate(services);
ConfigureService(builder);
ServiceLocator.Current = builder.Build();
ServiceLocator.GetService<ILoggerFactory>()
.AddConsole((c, l) => (int)l >= 3); } /// <summary>
/// 配置相关服务
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
private static void ConfigureService(ContainerBuilder builder)
{
builder.Initialize();
builder.RegisterServices();
builder.RegisterRepositories();
builder.RegisterModules();
var serviceBulider = builder
.AddClient()
.UseSharedFileRouteManager("c:\\routes.txt")
.UseDotNettyTransport();
} /// <summary>
/// 配置日志服务
/// </summary>
/// <param name="services"></param>
public static void ConfigureLogging(IServiceCollection services)
{
services.AddLogging();
} /// <summary>
/// 配置服务代理
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public static IServiceProxyFactory RegisterServiceProx(ContainerBuilder builder)
{
var serviceProxyFactory = ServiceLocator.GetService<IServiceProxyFactory>();
serviceProxyFactory.RegisterProxType(builder.GetInterfaceService().ToArray());
return serviceProxyFactory;
} }
}
远程服务调用
ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>(key)
本地模块和服务调用
ServiceLocator.GetService<T>(key)
5.负载均衡
surging提供3种负载均衡方式:
Random:随机,调用量越大分布越均匀,默认是这种方式
Polling:轮询,存在比较慢的机器容易在这台机器的请求阻塞较多
HashAlgorithm:一致性哈希,对于相同参数的请求路由到一个服务提供者上。
6.其他功能
surging还会提供分布式缓存,AOP数据拦截,基于rabbitmq订阅发布, 监控服务,后续完善后再来讲解。
6.性能测试
测试环境
CPU:Intel Core i7-4710MQ
内存:16G
硬盘:1T SSD+512G HDD
网络:局域网

7.总结
surging 0.0.0.1版本的发布意味着分布式微服务已经走出了第一步,以后还有很多工作需要完善。我会花很多空余时间去完善它。如果大家还有任何疑问或者感兴趣的话,可以加入QQ群:615562965
基于.NET CORE微服务框架 -surging的介绍和简单示例 (开源)的更多相关文章
- 基于.NET CORE微服务框架 -surging 基于messagepack、protobuffer、json.net 性能对比
1.前言 surging内部使用的是高性能RPC远程服务调用,如果用json.net序列化肯定性能上达不到最优,所以后面扩展了protobuf,messagepack序列化组件,以支持RPC二进制传输 ...
- 基于.NET CORE微服务框架 -谈谈surging API网关
1.前言 对于最近surging更新的API 网关大家也有所关注,也收到了不少反馈提出是否能介绍下Api网关,那么我们将在此篇文章中剥析下surging的Api 网关 开源地址:https://git ...
- 基于.NET CORE微服务框架 -浅析如何使用surging
1.前言 surging受到大家这么强烈的关注,我感到非常意外,比如有同僚在公司的分享会上分享surging, 还有在博客拿其它的RPC框架,微服务做对比等等,这些举动都让我感觉压力很大,毕竟作为个人 ...
- 基于.NET CORE微服务框架 -谈谈surging的服务容错降级
一.前言 对于不久开源的surging受到不少.net同学的青睐,也受到.net core学习小组的关注,邀请加入.NET China Foundation以方便国内.net core开源项目的推广, ...
- 基于.NET CORE微服务框架 -谈谈Cache中间件和缓存降级
1.前言 surging受到不少.net同学的青睐,也提了不少问题,提的最多的是什么时候集成API 网关,在这里回答大家最近已经开始着手研发,应该在1,2个月内会有个初版API网关,其它像Token身 ...
- .net Core 微服务框架 surging 使用
surging 是一个分布式微服务框架,提供高性能RPC远程服务调用,采用Zookeeper.Consul作为surging服务的注册中心, 集成了哈希,随机,轮询作为负载均衡的算法,RPC集成采用的 ...
- 基于.NET CORE微服务框架 -谈谈surging 的messagepack、protobuffer、json.net 序列化
1.前言 surging内部使用的是高性能RPC远程服务调用,如果用json.net序列化肯定性能上达不到最优,所以后面扩展了protobuf,messagepack序列化组件,以支持RPC二进制传输 ...
- 基于.NET CORE微服务框架 -Api网关服务管理
1.前言 经过10多天的努力,surging 网关已经有了大致的雏形,后面还会持续更新完善,请大家持续关注研发的动态 最近也更新了surging新的版本 更新内容: 1. 扩展Zookeeper封装2 ...
- 微服务框架surging学习之路——序列化 (转载https://www.cnblogs.com/alangur/p/10407727.html)
微服务框架surging学习之路——序列化 1.对微服务的理解 之前看到在群里的朋友门都在讨论微服务,看到他们的讨论,我也有了一些自己的理解,所谓微服务就是系统里的每个服务都 可以自由组合.自由组 ...
随机推荐
- Junit4测试Spring
使用Junit4.4测试 在类上的配置Annotation @RunWith(SpringJUnit4ClassRunner.class) 用于配置spring中测试的环境 @ContextCon ...
- MyBatis_Generator插件的安装以及简单使用
MyBatis_Generator_1.3.1.zip 1 下载安装包 安装包名称:MyBatis_Generator_1.3.1.zip 2 在Eclipse上进行安装 l ...
- Java经典编程题50道之八
求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字.例如2+22+222+2222+22222(此时共有5个数相加),几个数相加由键盘控制. public class Example ...
- 热部署环境下,dubbo序列化的bug和优化
一.问题的发现与解决 (1) 在热部署下,使用dubbo的序列化一个pojo对象,反序列化时报错:ClassNotFoundException. 最后发现原因是我们的框架选择使用了java序列 ...
- 以往CSDN博文目录
专栏一 原生javascript(3篇) 1. javascript立即执行函数详解 http://blog.csdn.net/faith1460/article/details/71600770 2 ...
- php简单的文件操作
(1)先要想好要操作哪个文件? (2)确定文件的路径? (3)要有什么文件管理功能? 一.先做一下简单的查看文件功能,文件中的文件和文件夹都显示,但是双击文件夹可以显示下一级子目录,双击"返 ...
- java书系列之——前言
第1章Java的起源 对于计算机语言的发展史,业界一般认为:B语言导致了C语言的诞生,C语言演变出了C++语言,而C++语言将让位于Java语言.要想更好地了解Java语言,就必须了解它产生的原因.推 ...
- Java 中Calendar、Date、SimpleDateFormat学习总结
在之前的项目中,经常会遇到Calendar,Date的一些操作时间的类,并且总会遇到时间日期之间的格式转化问题,虽然做完了但是总是忘记,记不清楚,每次还都要查找资料.今天总结一下,加深印象. Cale ...
- 【解决】使用compass watch xxx.scss 失败
原始日期:2016-01-25 16:49 在上一篇博客,我们终于安装好了compass,不过紧接着使用compass watch app.scss 结果失败,经过查询资料,是compass的版本问题 ...
- hibernate,createCriteria in条件 是一个集合。list 或 数组等
hibernate,createCriteria in条件 是一个集合.list 或 数组等 cq.in("states", new String[]{"2", ...