一、前言

至今为止编程开发已经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 能成为i最流行的技术。

surging从技术层面来说就是基于RPC协议的分布式微服务技术框架,框架依赖于Netty 进行异步通信,采用Zookeeper作为服务注册中心,集成了哈希,随机和轮询作为负载均衡算法

1.服务化应用基本框架

框架的执行过程如下:

1.服务提供者启动,根据RPC协议通过配置的IP和port绑定到netty上

2.注册服务信息存储至Zookeeper

3.客户端CreateProxy调用服务时,从内存中拿到上次通知的所有效的服务地址,根据路由信息和负载均衡机制选择最终调用的服务地址,发起调用

2.简单示例

  创建IModuleServices

IUserService.cs:

  1. [ServiceBundle] //服务标记
  2. public interface IUserService
  3. {
  4. Task<string> GetUserName(int id);
  5.  
  6. Task<bool> Exists(int id);
  7.  
  8. Task<int> GetUserId(string userName);
  9.  
  10. Task<DateTime> GetUserLastSignInTime(int id);
  11.  
  12. Task<UserModel> GetUser(int id);
  13.  
  14. Task<bool> Update(int id, UserModel model);
  15.  
  16. Task<IDictionary<string, string>> GetDictionary();
  17.  
  18. Task TryThrowException();
  19. }

创建领域对象

UserModel:

  1. [ProtoContract]
  2. public class UserModel
  3. {
  4. [ProtoMember(1)]
  5. public string Name { get; set; }
  6.  
  7. [ProtoMember(2)]
  8. public int Age { get; set; }
  9. }

AssemblyInfo.cs,扩展AssemblyModuleType来标识模块,根据AssemblyModuleType进行相关规则的反射注册

  1. [assembly: AssemblyTitle("Surging.IModuleServices.Common")]
  2. [assembly: AssemblyDescription("业务模块接口")]
  3. [assembly: AssemblyModuleType(ModuleType.InterFaceService)]
  4.  
  5. // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
  6. [assembly: Guid("2103624d-2bc2-4164-9aa5-1408daed9dee")]

创建Domain Service

PersonService.cs

  1. [ModuleName("Person")] //标识实例化名称
  2. public class PersonService : ServiceBase,IUserService
  3. {
  4. #region Implementation of IUserService
  5. private readonly UserRepository _repository;
  6. public PersonService(UserRepository repository)
  7. {
  8. this._repository = repository;
  9. }
  10.  
  11. public Task<string> GetUserName(int id)
  12. {
  13. return GetService<IUserService>("User").GetUserName(id);
  14. }
  15.  
  16. public Task<bool> Exists(int id)
  17. {
  18. return Task.FromResult(true);
  19. }
  20.  
  21. public Task<int> GetUserId(string userName)
  22. {
  23. return Task.FromResult(1);
  24. }
  25.  
  26. public Task<DateTime> GetUserLastSignInTime(int id)
  27. {
  28. return Task.FromResult(DateTime.Now);
  29. }
  30.  
  31. public Task<UserModel> GetUser(int id)
  32. {
  33. return Task.FromResult(new UserModel
  34. {
  35. Name = "fanly",
  36. Age = 18
  37. });
  38. }
  39.  
  40. public Task<bool> Update(int id, UserModel model)
  41. {
  42. return Task.FromResult(true);
  43. }
  44.  
  45. public Task<IDictionary<string, string>> GetDictionary()
  46. {
  47. return Task.FromResult<IDictionary<string, string>>(new Dictionary<string, string> { { "key", "value" } });
  48. }
  49.  
  50. public async Task Try()
  51. {
  52. Console.WriteLine("start");
  53. await Task.Delay(5000);
  54. Console.WriteLine("end");
  55. }
  56.  
  57. public Task TryThrowException()
  58. {
  59. throw new Exception("用户Id非法!");
  60. }
  61.  
  62. #endregion Implementation of IUserService
  63. }
  64. }

UserService.cs

  1. [ModuleName("User")]//标识实例化名称
  2. public class UserService: IUserService
  3. {
  4. #region Implementation of IUserService
  5. private readonly UserRepository _repository;
  6. public UserService(UserRepository repository)
  7. {
  8. this._repository = repository;
  9. }
  10.  
  11. public Task<string> GetUserName(int id)
  12. {
  13. return Task.FromResult($"id:{id} is name fanly.");
  14. }
  15.  
  16. public Task<bool> Exists(int id)
  17. {
  18. return Task.FromResult(true);
  19. }
  20.  
  21. public Task<int> GetUserId(string userName)
  22. {
  23. return Task.FromResult(1);
  24. }
  25.  
  26. public Task<DateTime> GetUserLastSignInTime(int id)
  27. {
  28. return Task.FromResult(DateTime.Now);
  29. }
  30.  
  31. public Task<UserModel> GetUser(int id)
  32. {
  33. return Task.FromResult(new UserModel
  34. {
  35. Name = "fanly",
  36. Age = 18
  37. });
  38. }
  39.  
  40. public Task<bool> Update(int id, UserModel model)
  41. {
  42. return Task.FromResult(true);
  43. }
  44.  
  45. public Task<IDictionary<string, string>> GetDictionary()
  46. {
  47. return Task.FromResult<IDictionary<string, string>>(new Dictionary<string, string> { { "key", "value" } });
  48. }
  49.  
  50. public async Task Try()
  51. {
  52. Console.WriteLine("start");
  53. await Task.Delay(5000);
  54. Console.WriteLine("end");
  55. }
  56.  
  57. public Task TryThrowException()
  58. {
  59. throw new Exception("用户Id非法!");
  60. }
  61.  
  62. #endregion Implementation of IUserService
  63. }
  64. }

AssemblyInfo.cs,扩展AssemblyModuleType来标识模块,根据AssemblyModuleType进行相关规则的反射注册

  1. [ModuleName("User")]//标识实例化名称
  2. public class UserService: IUserService
  3. {
  4. #region Implementation of IUserService
  5. private readonly UserRepository _repository;
  6. public UserService(UserRepository repository)
  7. {
  8. this._repository = repository;
  9. }
  10.  
  11. public Task<string> GetUserName(int id)
  12. {
  13. return Task.FromResult($"id:{id} is name fanly.");
  14. }
  15.  
  16. public Task<bool> Exists(int id)
  17. {
  18. return Task.FromResult(true);
  19. }
  20.  
  21. public Task<int> GetUserId(string userName)
  22. {
  23. return Task.FromResult(1);
  24. }
  25.  
  26. public Task<DateTime> GetUserLastSignInTime(int id)
  27. {
  28. return Task.FromResult(DateTime.Now);
  29. }
  30.  
  31. public Task<UserModel> GetUser(int id)
  32. {
  33. return Task.FromResult(new UserModel
  34. {
  35. Name = "fanly",
  36. Age = 18
  37. });
  38. }
  39.  
  40. public Task<bool> Update(int id, UserModel model)
  41. {
  42. return Task.FromResult(true);
  43. }
  44.  
  45. public Task<IDictionary<string, string>> GetDictionary()
  46. {
  47. return Task.FromResult<IDictionary<string, string>>(new Dictionary<string, string> { { "key", "value" } });
  48. }
  49.  
  50. public async Task Try()
  51. {
  52. Console.WriteLine("start");
  53. await Task.Delay(5000);
  54. Console.WriteLine("end");
  55. }
  56.  
  57. public Task TryThrowException()
  58. {
  59. throw new Exception("用户Id非法!");
  60. }
  61.  
  62. #endregion Implementation of IUserService
  63. }
  64. }

3.服务端

  1. using Autofac;
  2. using Autofac.Extensions.DependencyInjection;
  3. using Microsoft.Extensions.Configuration;
  4. using Microsoft.Extensions.DependencyInjection;
  5. using Microsoft.Extensions.Logging;
  6. using Surging.Core.Caching.Configurations;
  7. using Surging.Core.CPlatform;
  8. using Surging.Core.CPlatform.Runtime.Server;
  9. using Surging.Core.DotNetty;
  10. using Surging.Core.ProxyGenerator.Utilitys;
  11. using Surging.Core.System.Ioc;
  12. using Surging.Core.Zookeeper;
  13. using Surging.Core.Zookeeper.Configurations;
  14. using System;
  15. using System.Net;
  16. using System.Text;
  17. using System.Threading.Tasks;
  18.  
  19. namespace Surging.Services.Server
  20. {
  21. public class Program
  22. {
  23. static void Main(string[] args)
  24. {
  25. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  26. var services = new ServiceCollection();
  27. var builder = new ContainerBuilder();
  28. ConfigureLogging(services);
  29. builder.Populate(services);
  30. ConfigureService(builder);
  31. ServiceLocator.Current = builder.Build();
  32. ConfigureCache();
  33. ServiceLocator.GetService<ILoggerFactory>()
  34. .AddConsole((c, l) => (int)l >= 3);
  35. StartService();
  36. Console.ReadLine();
  37. }
  38.  
  39. /// <summary>
  40. /// 配置相关服务
  41. /// </summary>
  42. /// <param name="builder"></param>
  43. /// <returns></returns>
  44. private static void ConfigureService(ContainerBuilder builder)
  45. {
  46. builder.Initialize();
  47. builder.RegisterServices();
  48. builder.RegisterRepositories();
  49. builder.RegisterModules();
  50. builder.AddCoreServce()
  51. .AddServiceRuntime()
  52. .UseSharedFileRouteManager("c:\\routes.txt")//配置本地路由文件路径
  53. .UseDotNettyTransport()//配置Netty
  54. .UseZooKeeperRouteManager(new ConfigInfo("192.168.1.6:2181",
  55. "/dotnet/unitTest/serviceRoutes"));//配置ZooKeeper
  56. builder.Register(p => new CPlatformContainer(ServiceLocator.Current));
  57. }
  58.  
  59. /// <summary>
  60. /// 配置日志服务
  61. /// </summary>
  62. /// <param name="services"></param>
  63. public static void ConfigureLogging(IServiceCollection services)
  64. {
  65. services.AddLogging();
  66. }
  67.  
  68. /// <summary>
  69. /// 配置缓存服务
  70. /// </summary>
  71. public static void ConfigureCache()
  72. {
  73. new ConfigurationBuilder()
  74. .SetBasePath(AppContext.BaseDirectory)
  75. .AddCacheFile("cacheSettings.json", optional: false);
  76. }
  77.  
  78. /// <summary>
  79. /// 启动服务
  80. /// </summary>
  81. public static void StartService()
  82. {
  83. var serviceHost = ServiceLocator.GetService<IServiceHost>();
  84. Task.Factory.StartNew(async () =>
  85. {
  86. await serviceHost.StartAsync(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 98));
  87. Console.WriteLine($"服务端启动成功,{DateTime.Now}。");
  88. }).Wait();
  89. }
  90. }
  91. }

4.客户端

  1. using Autofac;
  2. using Autofac.Extensions.DependencyInjection;
  3. using Microsoft.Extensions.DependencyInjection;
  4. using Microsoft.Extensions.Logging;
  5. using Surging.Core.CPlatform;
  6. using Surging.Core.DotNetty;
  7. using Surging.Core.ProxyGenerator;
  8. using Surging.Core.ProxyGenerator.Utilitys;
  9. using Surging.Core.System.Ioc;
  10. using System.Text;
  11.  
  12. namespace Surging.Services.Client
  13. {
  14. public class Program
  15. {
  16. static void Main(string[] args)
  17. {
  18. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  19. var services = new ServiceCollection();
  20. var builder = new ContainerBuilder();
  21. ConfigureLogging(services);
  22. builder.Populate(services);
  23. ConfigureService(builder);
  24. ServiceLocator.Current = builder.Build();
  25. ServiceLocator.GetService<ILoggerFactory>()
  26. .AddConsole((c, l) => (int)l >= 3);
  27.  
  28. }
  29.  
  30. /// <summary>
  31. /// 配置相关服务
  32. /// </summary>
  33. /// <param name="builder"></param>
  34. /// <returns></returns>
  35. private static void ConfigureService(ContainerBuilder builder)
  36. {
  37. builder.Initialize();
  38. builder.RegisterServices();
  39. builder.RegisterRepositories();
  40. builder.RegisterModules();
  41. var serviceBulider = builder
  42. .AddClient()
  43. .UseSharedFileRouteManager("c:\\routes.txt")
  44. .UseDotNettyTransport();
  45. }
  46.  
  47. /// <summary>
  48. /// 配置日志服务
  49. /// </summary>
  50. /// <param name="services"></param>
  51. public static void ConfigureLogging(IServiceCollection services)
  52. {
  53. services.AddLogging();
  54. }
  55.  
  56. /// <summary>
  57. /// 配置服务代理
  58. /// </summary>
  59. /// <param name="builder"></param>
  60. /// <returns></returns>
  61. public static IServiceProxyFactory RegisterServiceProx(ContainerBuilder builder)
  62. {
  63. var serviceProxyFactory = ServiceLocator.GetService<IServiceProxyFactory>();
  64. serviceProxyFactory.RegisterProxType(builder.GetInterfaceService().ToArray());
  65. return serviceProxyFactory;
  66. }
  67.  
  68. }
  69. }

远程服务调用

  1. ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>(key)

本地模块和服务调用

  1. ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>(key)

5.负载均衡

surging提供3种负载均衡方式:

Random:随机,调用量越大分布越均匀,默认是这种方式

Polling:轮询,存在比较慢的机器容易在这台机器的请求阻塞较多

HashAlgorithm:一致性哈希,对于相同参数的请求路由到一个服务提供者上。

6.其他功能

surging还会提供分布式缓存,AOP数据拦截,基于rabbitmq订阅发布, 监控服务,后续完善后再来讲解。

6.性能测试

测试环境

CPU:Intel Core i7-4710MQ

内存:16G

硬盘:1T SSD+512G HDD

网络:局域网

测试结果如下:
1万次调用,也就2290MS,平均单次也就0.229毫秒,性能不错。

7.总结

surging 0.0.0.1版本的发布意味着分布式微服务已经走出了第一步,以后还有很多工作需要完善。我会花很多空余时间去完善它。如果大家还有任何疑问或者感兴趣的话,可以加入QQ群:615562965

基于.NET CORE微服务框架 -surging的介绍和简单示例 (开源)的更多相关文章

  1. 基于.NET CORE微服务框架 -surging 基于messagepack、protobuffer、json.net 性能对比

    1.前言 surging内部使用的是高性能RPC远程服务调用,如果用json.net序列化肯定性能上达不到最优,所以后面扩展了protobuf,messagepack序列化组件,以支持RPC二进制传输 ...

  2. 基于.NET CORE微服务框架 -谈谈surging API网关

    1.前言 对于最近surging更新的API 网关大家也有所关注,也收到了不少反馈提出是否能介绍下Api网关,那么我们将在此篇文章中剥析下surging的Api 网关 开源地址:https://git ...

  3. 基于.NET CORE微服务框架 -浅析如何使用surging

    1.前言 surging受到大家这么强烈的关注,我感到非常意外,比如有同僚在公司的分享会上分享surging, 还有在博客拿其它的RPC框架,微服务做对比等等,这些举动都让我感觉压力很大,毕竟作为个人 ...

  4. 基于.NET CORE微服务框架 -谈谈surging的服务容错降级

    一.前言 对于不久开源的surging受到不少.net同学的青睐,也受到.net core学习小组的关注,邀请加入.NET China Foundation以方便国内.net core开源项目的推广, ...

  5. 基于.NET CORE微服务框架 -谈谈Cache中间件和缓存降级

    1.前言 surging受到不少.net同学的青睐,也提了不少问题,提的最多的是什么时候集成API 网关,在这里回答大家最近已经开始着手研发,应该在1,2个月内会有个初版API网关,其它像Token身 ...

  6. .net Core 微服务框架 surging 使用

    surging 是一个分布式微服务框架,提供高性能RPC远程服务调用,采用Zookeeper.Consul作为surging服务的注册中心, 集成了哈希,随机,轮询作为负载均衡的算法,RPC集成采用的 ...

  7. 基于.NET CORE微服务框架 -谈谈surging 的messagepack、protobuffer、json.net 序列化

    1.前言 surging内部使用的是高性能RPC远程服务调用,如果用json.net序列化肯定性能上达不到最优,所以后面扩展了protobuf,messagepack序列化组件,以支持RPC二进制传输 ...

  8. 基于.NET CORE微服务框架 -Api网关服务管理

    1.前言 经过10多天的努力,surging 网关已经有了大致的雏形,后面还会持续更新完善,请大家持续关注研发的动态 最近也更新了surging新的版本 更新内容: 1. 扩展Zookeeper封装2 ...

  9. 微服务框架surging学习之路——序列化 (转载https://www.cnblogs.com/alangur/p/10407727.html)

    微服务框架surging学习之路——序列化   1.对微服务的理解 之前看到在群里的朋友门都在讨论微服务,看到他们的讨论,我也有了一些自己的理解,所谓微服务就是系统里的每个服务都 可以自由组合.自由组 ...

原文:https://www.bbsmax.com/A/VGzlVNkY5b/