基于.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 能成为i最流行的技术。

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

1.服务化应用基本框架

框架的执行过程如下:

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

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

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

2.简单示例

  创建IModuleServices

   IUserService.cs:

 创建领域对象

 UserModel:

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

 

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

?
1
2
3
4
5
6
[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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
[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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
[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进行相关规则的反射注册

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
[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.服务端

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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.客户端

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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;
         }
         
     }
}

 

远程服务调用

?
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版本的发布意味着分布式微服务已经走出了第一步,以后还有很多工作需要完善。我会花很多空余时间去完善它。

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值