XXL-RPC 是一个分布式服务框架,提供稳定高性能的RPC远程服务调用功能。拥有"高性能、分布式、注册中心、负载均衡、服务治理"等特性。现已开放源代码,开箱即用。javascript
RPC(Remote Procedure Call Protocol,远程过程调用),调用远程服务就像调用本地服务,在提供远程调用能力时不损失本地调用的语义简洁性;css
通常公司,尤为是大型互联网公司内部系统由上千上万个服务组成,不一样的服务部署在不一样机器,跑在不一样的JVM上,此时须要解决两个问题:html
“XXL-RPC”能够高效的解决这个问题:java
源码仓库地址 | Release Download |
---|---|
https://github.com/xuxueli/xxl-rpc | Download |
https://gitee.com/xuxueli0323/xxl-rpc | Download |
一、编译项目nginx
源码目录介绍:git
推荐使用 "XXL-REGISTRY" 做为注册中心。可前往 XXL-REGISTRY (https://github.com/xuxueli/xxl-registry ) 查看部署文档。很是轻量级,一分钟可完成部署工做。github
以示例项目 “xxl-rpc-sample-springboot” 为例讲解;算法
开发RPC服务的 “接口 / interface” 和 “数据模型 / DTO”;spring
可参考以下代码:
com.xxl.rpc.sample.api.DemoService com.xxl.rpc.sample.api.dto.UserDTO
需引入:XXL-RPC核心依赖 + 公共API接口依赖docker
<dependency> <groupId>com.xuxueli</groupId> <artifactId>xxl-rpc-core</artifactId> <version>${parent.version}</version> </dependency>
// 参考代码位置:com.xxl.rpc.sample.server.conf.XxlRpcProviderConfig @Bean public XxlRpcSpringProviderFactory xxlRpcSpringProviderFactory() { XxlRpcSpringProviderFactory providerFactory = new XxlRpcSpringProviderFactory(); providerFactory.setPort(port); providerFactory.setServiceRegistryClass(XxlRegistryServiceRegistry.class); providerFactory.setServiceRegistryParam(new HashMap<String, String>(){{ put(XxlRegistryServiceRegistry.XXL_REGISTRY_ADDRESS, address); put(XxlRegistryServiceRegistry.ENV, env); }}); logger.info(">>>>>>>>>>> xxl-rpc provider config init finish."); return providerFactory; }
ProviderFactory 参数 | 说明 |
---|---|
netType | 服务通信方案,可选范围:NETTY(默认)、NETTY_HTTP ; |
serialize | 序列化方案,可选范围: HESSIAN(默认)、HESSIAN1 ; |
ip | 服务方IP,为空自动获取机器IP,支持手动指定 |
port | 服务方端口,默认 7080 |
accessToken | 服务鉴权Token,非空时生效; |
serviceRegistryClass | 服务注册中心,可选范围:LocalServiceRegistry.class、ZkServiceRegistry.class;支持灵活自由扩展; |
serviceRegistryParam | 服务注册中心启动参数,参数说明可参考各注册中心实现的 start() 的方法注释; |
实现 “服务API” 的接口,开发业务逻辑代码;
可参考以下代码:
com.xxl.rpc.sample.api.DemoService 注意: 一、添加 “@Service” 注解:被Spring容器扫描识别为SpringBean; 二、添加 “@XxlRpcService” 注解:被 “XXL-RPC” 的 ProviderFactory 扫描识别,进行Provider服务注册,若是开启注册中心同时也会进行注册中心服务注册;
“@XxlRpcService” 注解参数 | 说明 |
---|---|
version | 服务版本,默认空;可据此区分同一个“服务API” 的不一样版本; |
需引入:XXL-RPC核心依赖 + 公共API接口依赖
<dependency> <groupId>com.xuxueli</groupId> <artifactId>xxl-rpc-core</artifactId> <version>${parent.version}</version> </dependency>
// 参考代码位置:com.xxl.rpc.sample.client.conf.XxlRpcInvokerConfig @Bean public XxlRpcSpringInvokerFactory xxlJobExecutor() { XxlRpcSpringInvokerFactory invokerFactory = new XxlRpcSpringInvokerFactory(); invokerFactory.setServiceRegistryClass(XxlRegistryServiceRegistry.class); invokerFactory.setServiceRegistryParam(new HashMap<String, String>(){{ put(XxlRegistryServiceRegistry.XXL_REGISTRY_ADDRESS, address); put(XxlRegistryServiceRegistry.ENV, env); }}); logger.info(">>>>>>>>>>> xxl-rpc invoker config init finish."); return invokerFactory; }
InvokerFactory 参数 | 说明 |
---|---|
serviceRegistryClass | 服务注册中心,可选范围:LocalServiceRegistry.class、ZkServiceRegistry.class;支持灵活自由扩展; |
serviceRegistryParam | 服务注册中心启动参数,参数说明可参考各注册中心实现的 start() 的方法注释; |
// 参考代码位置:com.xxl.rpc.sample.client.controller.IndexController @XxlRpcReference private DemoService demoService; …… UserDTO user = demoService.sayHi(name); ……
“@XxlRpcReference” 注解参数 | 说明 |
---|---|
netType | 服务通信方案,可选范围:NETTY(默认)、NETTY_HTTP; |
serializer | 序列化方案,可选范围: HESSIAN(默认)、HESSIAN1; |
address | 服务远程地址,ip:port 格式;选填;非空时将会优先实用该服务地址,为空时会从注册中心服务地址发现; |
accessToken | 服务鉴权Token,非空时生效; |
version | 服务版本,默认空;可据此区分同一个“服务API” 的不一样版本; |
timeout | 服务超时时间,单位毫秒; |
callType | 请求类型,可选范围:SYNC(默认)、ONEWAY、FUTURE、CALLBACK; |
// 参考代码位置:com.xxl.rpc.sample.client.controller.IndexController
代码中将上面配置的消费方 invoker 远程服务注入到测试 Controller 中使用,调用该服务,查看看是否正常。 若是正常,说明该接口项目经过XXL-RPC从 client 项目调用了 server 项目中的服务,夸JVM进行了一次RPC通信。
访问该Controller地址便可进行测试:http://127.0.0.1:8081/?name=jack
得益于优良的兼容性与模块化设计,不限制外部框架;除 spring/springboot 环境以外,理论上支持运行在任何Java代码中,甚至main方法直接启动运行;
以示例项目 “xxl-rpc-sample-frameless” 为例讲解;该示例项目以直连IP方式进行演示,也能够选择接入注册中心方式使用,如接入 XXL-REGISTRY。
// 参考代码位置:com.xxl.rpc.sample.server.XxlRpcServerApplication // init XxlRpcProviderFactory providerFactory = new XxlRpcProviderFactory(); providerFactory.initConfig(NetEnum.NETTY, Serializer.SerializeEnum.HESSIAN.getSerializer(), -1, -1, null, 7080, null, null, null); // add services providerFactory.addService(DemoService.class.getName(), null, new DemoServiceImpl()); // start providerFactory.start(); while (!Thread.currentThread().isInterrupted()) { TimeUnit.HOURS.sleep(1); } // stop providerFactory.stop();
// 参考代码位置:com.xxl.rpc.sample.client.XxlRpcClientAplication // init client DemoService demoService = (DemoService) new XxlRpcReferenceBean(NetEnum.NETTY, Serializer.SerializeEnum.HESSIAN.getSerializer(), CallType.SYNC, DemoService.class, null, 500, "127.0.0.1:7080", null, null).getObject(); // test UserDTO userDTO = demoService.sayHi("[SYNC]jack"); System.out.println(userDTO);
提供稳定高性能的RPC远程服务调用功能,简化分布式服务通信开发。
概念:
RPC通信,可大体划分为四个步骤,可参考上图进行理解:(XXL-RPC提供了多种调用方案,此处以 “SYNC” 方案为例讲解;)
consumer和provider采用NIO方式通信,其中TCP通信方案可选NETTY具体选型,高吞吐高并发;可是仅仅依靠单个TCP链接进行数据传输存在瓶颈和风险,所以XXL-RPC在consumer端自身实现了内部链接池,consumer和provider之间为了一个链接池,当尽情底层通信是会取出一条TCP链接进行通信(可参考上图)。
XXL-RPC采用NIO进行底层通信,可是NIO是异步通信模型,调用线程并不会阻塞获取调用结果,所以,XXL-RPC实现了在异步通信模型上的同步调用,即“sync-over-async”,实现原理以下,可参考上图进行理解:
XXL-RPC的注册中心,是可选组件,支持服务注册并动态发现;
可选择不启用,直接指定服务提供方机器地址通信;
选择启用时,内置可选方案:“XXL-REGISTRY 轻量级注册中心”(推荐)、“ZK注册中心”、“Local注册中心”等;
推荐使用内置的 "XXL-REGISTRY" 做为注册中心。可前往 XXL-REGISTRY (https://github.com/xuxueli/xxl-registry ) 查看部署文档。很是轻量级,一分钟可完成部署工做。
更易于集群部署、横向扩展,搭建与学习成本更低,推荐采用该方式;
内置“ZK注册中心”,可选组件,结构图以下:
原理:
XXL-RPC中每一个服务在zookeeper中对应一个节点,如图"iface name"节点,该服务的每个provider机器对应"iface name"节点下的一个子节点,如图中"192.168.0.1:9999"、"192.168.0.2:9999"和"192.168.0.3:9999",子节点类型为zookeeper的EPHMERAL类型,该类型节点有个特色,当机器和zookeeper集群断掉链接后节点将会被移除。consumer底层能够从zookeeper获取到可提供服务的provider集群地址列表,从而能够向其中一个机器发起RPC调用。
服务提供方新增 "/services" 服务目录功能,可查看在线服务列表;暂时仅针对NETTY_HTTP通信方案,浏览器访问地址 "{端口地址}/services" 便可。
XXL-RPC提供多中通信方案:支持 TCP 和 HTTP 两种通信方式进行服务调用;其中 TCP 提供可选方案 NETTY ,HTTP 提供可选方案 NETTY_HTTP (新版本移除了Mina和Jetty通信方案,主推Netty;若是有须要能够参考旧版本;);
若是须要切换XXL-RPC“通信方案”,只须要执行如下两个步骤便可:
XXL-RPC的注册中心,是一个可选组件,不强制依赖;支持服务注册并动态发现;
可选择不启用,直接指定服务提供方机器地址通信;
选择启用时,原生提供多种开箱即用的注册中心可选方案,包括:“XXL-RPC原生轻量级注册中心”、“ZK注册中心”、“Local注册中心”等;
若是须要切换XXL-RPC“注册中心”,只须要执行如下两个步骤便可:
XXL-RPC 提供 "泛华调用" 支持,服务调用方不依赖服务方提供的API;泛化调用一般用于框架集成,好比 "网关平台、跨语言调用、测试平台" 等; 开启 "泛华调用" 时服务方不须要作任何调整,仅须要调用方初始化一个泛华调用服务Reference ("XxlRpcGenericService") 便可。
“XxlRpcGenericService#invoke” 请求参数 | 说明 |
---|---|
String iface | 服务接口类名 |
String version | 服务版本 |
String method | 服务方法 |
String[] parameterTypes | 服务方法形参-类型,如 "int、java.lang.Integer、java.util.List、java.util.Map ..." |
Object[] args | 服务方法形参-数据 |
// 服务Reference初始化-注解方式示例 @XxlRpcReference private XxlRpcGenericService genericService; // 服务Reference初始化-API方式示例 XxlRpcGenericService genericService = (XxlRpcGenericService) new XxlRpcReferenceBean(……).getObject(); // 调用方示例 Object result = genericService.invoke( "com.xxl.rpc.sample.server.service.Demo2Service", null, "sum", new String[]{"int", "int"}, new Object[]{1, 2} ); // 服务方示例 public class Demo2ServiceImpl implements Demo2Service { @Override public int sum(int a, int b) { return a + b; } }
欢迎参与项目贡献!好比提交PR修复一个bug,或者新建 Issue 讨论新特性或者变动。
更多接入的公司,欢迎在 登记地址 登记,登记仅仅为了产品推广。
产品开源免费,而且将持续提供免费的社区技术支持。我的或企业内部可自由的接入和使用。
不管金额多少都足够表达您这份心意,很是感谢 :) 前往捐赠