基于.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,一经查实,立即删除!

相关文章

ssl2331OJ1373-鱼塘钓鱼 之2【贪心堆优化】

前言 上篇&#xff1a;纯贪心做法 下篇&#xff1a;dp做法 题目&#xff1a;OJ1373 正题 有N个鱼塘&#xff0c;给出每分钟可以钓到的鱼数和每钓一次下一次钓减少的鱼数和到下一个鱼塘需要几分钟&#xff08;不能回头&#xff09;。求限定时间内最多能够钓到的鱼数 解题思路…

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;…

JDBC登录功能实现

模拟淘宝登录 package com.bjsxt.jdbc2;import com.bjsxt.entity.User; import entity.Emp;import java.nio.file.attribute.UserDefinedFileAttributeView; import java.sql.*; import java.util.ArrayList; import java.util.List; import java.util.Scanner;/*** 模拟淘宝登…

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…

ssl2331OJ1373-鱼塘钓鱼 之3【dp】

前言 上篇&#xff1a; 纯贪心做法 堆优化贪心 题目&#xff1a;OJ1373 正题 有N个鱼塘&#xff0c;给出每分钟可以钓到的鱼数和每钓一次下一次钓减少的鱼数和到下一个鱼塘需要几分钟&#xff08;不能回头&#xff09;。求限定时间内最多能够钓到的鱼数 解题思路 用f[i][…

多线程三种创建方式

方法一&#xff1a;继承Thread Thread package com.bjsxt.create;/*** author dell* data 2021/3/2* 创建一个线程对象&#xff0c;并启动线程** 注意&#xff1a;启动main方法&#xff0c;自动创建main线程* * thread.join() 阻塞乌龟线程&#xff0c;乌龟执行完…

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

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

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

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

OJ1306-最长公共子上升序列【dp】

前言 这是一道比较久之前的题了&#xff0c;之前没做完。不过这次不是因为我改了&#xff0c;而是数据改了&#xff08;可能之前有问题&#xff09;&#xff0c;然后偶然今天翻的时候就发现自己对了QAQ。 题目 OJ1306 就是给出两个序列&#xff0c;求出这两个序列中公共的最…

多线程三种同步方式(模拟银行取款)

方法一&#xff1a;同步代码块 Accoun package com.bjsxt.synch1;/*** 银行账户类*/ public class Account {private int balance 600;//余额/*** 取款* param money*/public void withDraw(int money){this.balance this.balance -money;}/*** 查看余额* return*/public i…

今天就唠叨唠叨吧……

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

利用redis保存验证码并设置过期时间

package com.atguigu.jedis;import redis.clients.jedis.Jedis;import java.util.Random;public class PhoneCode {public static void main(String[] args) {//模拟验证码发送verifyCode("13678765435");//模拟验证码校验//getRedisCode("13678765435",&q…

洛谷P2085ssl1411OJ1370-最小函数值【堆,贪心】

前言 有一个东西卡了我一会 折叠N*或N 正整数集 (由全体正整数组成的集合) N*:{1,2,3,…,n,…} 题目 洛谷P2085 OJ1370 给出n个ai,bi,ci。定义一个函数 fi(x)aix2bixci(x∈N∗)fi(x)aix2bixci(x∈N∗)然后求最小的m个数解题思路 这道题比较简单&#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…

多线程的线程通信(生产消费)

消费者线程 package com.bjsxt.commu5;/*** 消费者线程*/ public class ConsumeRunnable implements Runnable {//private Product product new Product();private Product product;private Object obj new Object();public ConsumeRunnable() {}public ConsumeRunnable(Pr…

19级:一天一瞬间

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