.Net分布式微服务框架surging

.Net分布式微服务框架surging

  • 开源协议:未知
  • 操作系统: Windows Linux OS X
  • 开发语言:C#
  • 项目所有者:fanliang11
  • 收录时间:2017-07-09
  • 分享:
编辑评级
4

项目详细介绍

surging是博客园的一个网友开源的分布式微服务框架,提供高性能RPC远程服务调用,采用Zookeeper作为surging服务的注册中心,集成了哈希,随机,轮询作为负载均衡的算法,RPC集成采用的是netty框架,采用异步传输。

主要特点:

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 GetUserName(int id);

        Task Exists(int id);

        Task  GetUserId(string userName);

        Task GetUserLastSignInTime(int id);

        Task GetUser(int id);

        Task Update(int id, UserModel model);

        Task> 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 GetUserName(int id)
        {
            return GetService("User").GetUserName(id);
        }

        public Task Exists(int id)
        {
            return Task.FromResult(true);
        }

        public Task GetUserId(string userName)
        {
            return Task.FromResult(1);
        }

        public Task GetUserLastSignInTime(int id)
        {
            return Task.FromResult(DateTime.Now);
        }

        public Task GetUser(int id)
        {
            return Task.FromResult(new UserModel
            {
                Name = "fanly",
                Age = 18
            });
        }

        public Task Update(int id, UserModel model)
        {
            return Task.FromResult(true);
        }

        public Task> GetDictionary()
        {
            return Task.FromResult>(new Dictionary { { "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 GetUserName(int id)
        {
            return Task.FromResult($"id:{id} is name fanly.");
        }

        public Task Exists(int id)
        {
            return Task.FromResult(true);
        }

        public Task GetUserId(string userName)
        {
            return Task.FromResult(1);
        }

        public Task GetUserLastSignInTime(int id)
        {
            return Task.FromResult(DateTime.Now);
        }

        public Task GetUser(int id)
        {
            return Task.FromResult(new UserModel
            {
                Name = "fanly",
                Age = 18
            });
        }

        public Task Update(int id, UserModel model)
        {
            return Task.FromResult(true);
        }

        public Task> GetDictionary()
        {
            return Task.FromResult>(new Dictionary { { "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 GetUserName(int id)
        {
            return Task.FromResult($"id:{id} is name fanly.");
        }

        public Task Exists(int id)
        {
            return Task.FromResult(true);
        }

        public Task GetUserId(string userName)
        {
            return Task.FromResult(1);
        }

        public Task GetUserLastSignInTime(int id)
        {
            return Task.FromResult(DateTime.Now);
        }

        public Task GetUser(int id)
        {
            return Task.FromResult(new UserModel
            {
                Name = "fanly",
                Age = 18
            });
        }

        public Task Update(int id, UserModel model)
        {
            return Task.FromResult(true);
        }

        public Task> GetDictionary()
        {
            return Task.FromResult>(new Dictionary { { "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()
                   .AddConsole((c, l) => (int)l >= 3);
            StartService();
            Console.ReadLine();
        }

        /// 
        /// 配置相关服务
        /// 
        ///
        /// 
        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));
        }

        /// 
        /// 配置日志服务
        /// 
        ///
        public static void ConfigureLogging(IServiceCollection services)
        {
            services.AddLogging();
        }

        /// 
        /// 配置缓存服务
        /// 
        public static void ConfigureCache()
        {
            new ConfigurationBuilder()
           .SetBasePath(AppContext.BaseDirectory)
           .AddCacheFile("cacheSettings.json", optional: false);
        }

        /// 
        /// 启动服务
        /// 
        public static void StartService()
        {
            var serviceHost = ServiceLocator.GetService();
            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()
                .AddConsole((c, l) => (int)l >= 3);
           
        }

        /// 
        /// 配置相关服务
        /// 
        ///
        /// 
        private static void ConfigureService(ContainerBuilder builder)
        {
            builder.Initialize();
            builder.RegisterServices();
            builder.RegisterRepositories();
            builder.RegisterModules();
            var serviceBulider = builder
                 .AddClient()
                 .UseSharedFileRouteManager("c:\\routes.txt")
                 .UseDotNettyTransport();
        }

        /// 
        /// 配置日志服务
        /// 
        ///
        public static void ConfigureLogging(IServiceCollection services)
        {
            services.AddLogging();
        }

        /// 
        /// 配置服务代理
        /// 
        ///
        /// 
        public static IServiceProxyFactory RegisterServiceProx(ContainerBuilder builder)
        {
            var serviceProxyFactory = ServiceLocator.GetService();
            serviceProxyFactory.RegisterProxType(builder.GetInterfaceService().ToArray());
            return serviceProxyFactory;
        }
        
    }
}

 

远程服务调用

ServiceLocator.GetService().CreateProxy(key)

 

本地模块和服务调用

ServiceLocator.GetService().CreateProxy(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毫秒,性能不错。

 

更多介绍,详见作者的博客地址:http://www.cnblogs.com/fanliang11/p/7049472.html

 

标签:微服务  surging