基于.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。开源地址:https://github.com/fanliang11/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:


[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<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

相关文章

  • 谷歌发布的首款基于HTTP/2和protobuf的RPC框架:GRPC

  • 拥抱.NET Core,跨平台的轻量级RPC:Rabbit.Rpc

  • 基于DotNet Core的RPC框架(一) DotBPE.RPC快速开始

原文地址:http://www.cnblogs.com/fanliang11/p/7049472.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324731.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NLP Coursera By Michael Collins - Week1

转载自 NLP Coursera By Michael Collins - Week1 NLP Coursera By Michael Collins - Week1 构建模型框架 - Markov Process 毕竟是机器学习嘛&#xff0c;所以第一步&#xff0c;先要把实际问题转化成数学模型。 在NLP中&#xff0c;一般使用的都是概率模型&#xff0c;…

19级:班级日常分享,一天一瞬间

点击上方蓝色关注我们&#xff01;19级的同学们目前正在做KTV点歌系统项目&#xff0c;截止今日为止&#xff0c;项目已经进展了1天多了&#xff0c;进度还在可控范围内&#xff0c;大部分组的后台都已完成&#xff0c;刘娜小组稍微比较慢了点儿。李磊小组的进度最快&#xff0…

Attentive Sequence to Sequence Networks

转载自 Attentive Sequence to Sequence Networks Attentive Sequence to Sequence Networks 1、Encoder-Decoder 框架 首先我们模型的整体框图如下&#xff1a; Encoder-Decoder 框架可以这么直观地去理解&#xff1a;可以把它看作适合处理由一个句子&#xff08;或篇章&a…

20级四班班级管理规章制度

点击上方蓝色关注我们&#xff01;

完全图解RNN、RNN变体、Seq2Seq、Attention机制

转载自 完全图解RNN、RNN变体、Seq2Seq、Attention机制 完全图解RNN、RNN变体、Seq2Seq、Attention 机制 本文首发于知乎专栏“ai insight”&#xff01; 本文主要是利用图片的形式&#xff0c;详细地介绍了经典的RNN、RNN几个重要变体&#xff0c;以及Seq2Seq模型、Attent…

今天就唠叨唠叨吧……

点击上方蓝色关注我们&#xff01;看书这个爱好是从去年年底开始的。看关于教育教学管理类型的书籍是从今年前半年开始的&#xff0c;有好些书都是王晓春老师写的&#xff0c;例如《做一个专业的班主任》、《问题学生诊疗手册》《今天怎样做教师》&#xff0c;每本书都有不一样…

如何轻松愉快的理解条件随机场(CRF)

转载自 如何轻松愉快的理解条件随机场&#xff08;CRF&#xff09; 如何轻松愉快的理解条件随机场&#xff08;CRF&#xff09;&#xff1f; 理解条件随机场最好的办法就是用一个现实的例子来说明它。 但是目前中文的条件随机场文章鲜有这样干的&#xff0c;可能写文章的人…

ASP.NET Core MVC 控制器创建与依赖注入

在我最后一篇关于 ASP.NET Core 释放IDsiposable对象的文章&#xff08;中文、英文原文&#xff09;中&#xff0c;Mark Rendle 指出&#xff0c;MVC 控制器在请求结束时也会释放资源。乍一看&#xff0c;此范围内的资源在请求结束时会释放似乎是显而易见的&#xff0c;但是 MV…

19级:一天一瞬间

点击上方蓝色关注我们&#xff01;3班的KTV项目周期为两周&#xff0c;目前时间将近一周&#xff0c;除李磊小组进度超出之外&#xff0c;其余四个小组的进度都属正常。上午大致的将每个小组的前台功能过了一遍&#xff0c;刘文瑞小组还剩几个点歌功能未实现&#xff0c;整体的…

拥抱.NET Core系列:依赖注入(2)

上一篇“拥抱.NET Core系列&#xff1a;依赖注入&#xff08;1&#xff09;大体介绍了服务注册、获取和生命周期&#xff0c;这一篇来做一些补充。由于内容跨度大&#xff08;.NET Core、ASP.NET Core&#xff09;&#xff0c;所以文章并不是非常的贯穿&#xff0c;大家可以挑着…

使用Docker 实现微服务并搭建博客,一文全掌握

转载自 使用Docker 实现微服务并搭建博客&#xff0c;一文全掌握 Docker 是一个容器工具&#xff0c;提供虚拟环境。很多人认为&#xff0c;它改变了我们对软件的认识。 本文&#xff0c;通过搭建一个博客的例子&#xff0c;来介绍如何使用Docker实现微服务。 站在 Docker …

失望至极……

点击上方蓝色关注我们&#xff01;

asp.net core新特性(1):TagHelper

进步&#xff0c;才是人应该有的现象。—— 雨果 今天开始&#xff0c;我就来说说asp.net core的新特性&#xff0c;今天就说说TagHelper标签助手。虽然学习.net&#xff0c;最有帮助的就是microsoft的官方说明文档了&#xff0c;里面把一些使用说明都写的非常清楚&#xff0c;…

Java中的事务——全局事务与本地事务

转载自 Java中的事务——全局事务与本地事务 在上一篇文章中说到过&#xff0c;Java事务的类型有三种&#xff1a;JDBC事务、JTA(Java Transaction API)事务、容器事务。 这是从事务的实现角度区分的&#xff0c;本文从另外一个角度来再次区分一下Java中的事务。站在事务管…

SSM整合简单登录案例

[1] 在数据库中创建用户信息表 [2] 搭建SSM开发环境 使用idea创建登录功能的web项目 在web-inf目录下创建lib文件夹&#xff0c;并导入SSM的jar包. 在src下创建MVC的包结构 在src下创建并配置SSM的xml文件 ① applicationcontext.xml <?xml version"1.0"…

19级、20级:班级日常分享,一天一瞬间

点击上方蓝色关注我们&#xff01;由于近期班级里面总是有或大或小的问题&#xff0c;所以就和丁老师商量的制定了长达29条的班规&#xff0c;昨天利用下午上课的时间在班内逐条讲解。因为班规是以安全、学习、道德以及身心健康为中心出发的&#xff0c;所以条条都合理&#xf…

同步VS异步

同步异步 &#xff0c; 举个例子来说&#xff0c;一家餐厅吧来了5个客人&#xff0c;同步的意思就是说&#xff0c;来第一个点菜&#xff0c;点了个鱼&#xff0c;好&#xff0c; 厨师去捉鱼杀鱼&#xff0c;过了半小时鱼好了给第一位客人&#xff0c;开始下位一位客人&#xf…

面向 Visual Studio 开发者的 Git 内部源代码

在我撰写的 Git DevOps 文章 (msdn.com/magazine/mt767697) 中&#xff0c;我介绍了 Git 版本控制系统 (VCS) 与可能已经很熟悉的集中式 VCS 的区别。然后&#xff0c;我演示了如何在 Visual Studio 中使用 Git 工具完成一些 Git 任务。在本文中&#xff0c;我将汇总 Git 在新发…