基于接口的调用远比基于基础消息交互来得更简单和便于维护,特别在业务展现上,接口作为业务表现更适合其便利性。为了让SmartRoute更适合业务应用集成,在新的一年开始SmartRoute集成了远程接口调用功能。基于SmartRoute的基础特性,在这基础上扩展的接口调用会变得更简单灵活,其特别点如下:并不需要知道服务地址,只需要明确接口和方法即可以实现远程服务调用;无需任何配置即可实现负载和故障迁移。而这一系列的更利功能都归攻于SmartRoute基础建设!
SmartRoute的远程接口调用是基于Protobuf的RPC实现,其制定服务是以接口为基础有点似于wcf,但调会变得更透明简单.以下针对组件实现一个简单的远程接口调用和负载处理。
接口定义
组件对接口的定义并没有什么特别要求或添加特性,但接口方法的定义不支持同名称重载,现有版本的组件暂不支持。对于out和ref类型的参数也暂不支持。以下是定义一个简单的用户操作接口:
public interface IUserService { DateTime Register(string name, string email); void ChangePWD(string name, string oldpwd, string newpwd); }
注册口服务
接口定义后需要针对接口进行实现才能注册到服务中,组件是通过SwitchSubscriber来挂载接口服务;首先是初始化通讯节点,然后在这节点服务基础上构建相应的SwitchSubscriber订阅器,基于订阅器即可以进行服务注册。
public class Program : IUserService { public static void Main(string[] args) { INode node = SmartRoute.NodeFactory.Default; node.Loger.Type = LogType.ALL; node.AddLogHandler(new SmartRoute.ConsoleLogHandler(LogType.ALL)); node.Open(); SwitchSubscriber rmiserver = new SwitchSubscriber(node); rmiserver.Register<IUserService>(new Program()); System.Threading.Thread.Sleep(-1); } public void ChangePWD(string name, string oldpwd, string newpwd) { Console.WriteLine("ChangePWD {0}/{1}/{2}", name, oldpwd, newpwd); } public DateTime Register(string name, string email) { Console.WriteLine("register {0}/{1}", name, email); return DateTime.Now; } }
对于以上服务注册代码相信有朋友会感觉奇怪,为什么没有绑定服务地址类似的代码?其实这也是组件的特点之一,在整个通讯应用过程中都不需要了解服务地址这一概念,通讯所需要的要求在组件中都完全被透明化了。
调用实现
基于服务的调用也是在SwitchSubscriber的基础上进行处理,由于组件暂没实现接口代理的动态实现,所以现阶段只能通过手动实现接口的代理类了。
public class UserService : IUserService { public UserService(SwitchSubscriber context) { this.Context = context; } public SwitchSubscriber Context { get; set; } public void ChangePWD(string name, string oldpwd, string newpwd) { Context.MethodInvoke("IUserService", "ChangePWD", name, oldpwd, newpwd); } public DateTime Register(string name, string email) { return Context.MethodInvoke<DateTime>("IUserService", "Register", name, email); } }
接口的实现通过SwitchSubscriber调用相关接口方法名称传入相关参数即可,由于组件并不需要知道通讯细节所以也不需要指定接口服务地址的工作。调用和服务处理一样定义节点并开启构建相关SwitchSubscriber对象即可使用。
INode node = NodeFactory.Default; node.Loger.Type = LogType.ALL; node.AddLogHandler(new ConsoleLogHandler(LogType.ALL)); node.Open(); SwitchSubscriber rmiserver = new SwitchSubscriber(node); mUserService = new UserService(rmiserver); DateTime result = mUserService.Register("henry" + i, "[email protected]"); Console.WriteLine(result);
实际应用效果截图
负载和迁移
在实际应用中服务必须存在负载和故障迁移,如何为接口服务添加这些功能复杂吗?由于组件基础已经集成了这些功能,所以在代码上并不需要任何调用就能实现多节点负载和故障处理;只要编写的服务启动一个新的服务,调用者就会自动发现并进行负载调用;同样如果一个节点现出通讯异常后,调用者会自动路由到正常的节点服务中。这一系列的措施都是全自动并不需要配置或代码来处理!
?
[了解详情组件开源地址:https://github.com/IKende/SmartRoute]