-
Notifications
You must be signed in to change notification settings - Fork 922
介绍surging
什么是surging
surging从中文译义来说,冲击,汹涌,也可以翻译成风起云涌。我所希望的是.net core 能成为最流行的技术。
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 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:]
创建Domain Service
PersonService.cs
[ModuleName("Person")] //标识实例化名称
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;
}
/// <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(); }
} }
远程服务调用
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