最好的开源rpc(微博轻量级RPC框架)
概述
Motan 是一套高性能、易于使用的分布式远程服务调用(RPC)框架。
功能
- 支持通过spring配置方式集成,无需额外编写代码即可为服务提供分布式调用能力。
- 支持集成consul、ZooKeeper等配置服务组件,提供集群环境的服务发现及治理能力。
- 支持动态自定义负载均衡、跨机房流量调整等高级服务调度能力。
- 基于高并发、高负载场景进行优化,保障生产环境下RPC服务高可用。
简单调用示例
同步调用
- 在pom中添加依赖
<dependency> <groupId>com.weibo</groupId> <artifactId>motan-core</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>com.weibo</groupId> <artifactId>motan-transport-netty</artifactId> <version>RELEASE</version> </dependency> <!-- only needed for spring-based features --> <dependency> <groupId>com.weibo</groupId> <artifactId>motan-springsupport</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.4.RELEASE</version> </dependency>
- 为调用方和服务方创建公共接口。
- src/main/java/quickstart/FooService.java
package quickstart; public interface FooService { public String hello(String name); }
- 编写业务接口逻辑、创建并启动RPC Server。
- src/main/java/quickstart/FooServiceImpl.java
package quickstart; public class FooServiceImpl implements FooService { public String hello(String name) { System.out.println(name " invoked rpc service"); return "hello " name; } }
- src/main/resources/motan_server.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:motan="http://api.weibo.com/schema/motan" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://api.weibo.com/schema/motan http://api.weibo.com/schema/motan.xsd"> <!-- service implemention bean --> <bean id="serviceImpl" class="quickstart.FooServiceImpl" /> <!-- exporting service by Motan --> <motan:service interface="quickstart.FooService" ref="serviceImpl" export="8002" /> </beans> `src/main/java/quickstart/server.java` package quickstart; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Server { public static void main(String[] args) throws InterruptedException { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:motan_server.xml"); System.out.println("server start..."); } }
- 执行Server类中的main函数将会启动Motan服务,并监听8002端口.
- 创建并执行RPC Client。
- src/main/resources/motan_client.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:motan="http://api.weibo.com/schema/motan" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://api.weibo.com/schema/motan http://api.weibo.com/schema/motan.xsd"> <!-- reference to the remote service --> <motan:referer id="remoteService" interface="quickstart.FooService" directUrl="localhost:8002"/> </beans>
- src/main/java/quickstart/Client.java
package quickstart; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Client { public static void main(String[] args) throws InterruptedException { ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:motan_client.xml"); FooService service = (FooService) ctx.getBean("remoteService"); System.out.println(service.hello("motan")); } }
- 执行Client类中的main函数将执行一次远程调用,并输出结果。
异步调用
异步调用与同步调用基本配置完全一样,只需要在接口类中加上@MotanAsync注解,然后client端稍作修改。server端不需要做任何修改。具体步骤如下:
- 在接口类上加@MotanAsync注解
package quickstart; @MotanAsync public interface FooService { public String hello(String name); }
- 编译时,Motan自动生成异步service类,生成路径为target/generated-sources/annotations/,生成的类名为service名加上Async,例如service类名为FooService.java,则自动生成的类名为FooServiceAsync.java。 另外,需要将motan自动生产类文件的路径配置为项目source path,可以使用maven plugin或手动配置。pom.xml配置如下:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>RELEASE</version> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>add-source</goal> </goals> <configuration> <sources> <source>${project.build.directory}/generated-sources/annotations</source> </sources> </configuration> </execution> </executions> </plugin>
- 在client端配置motan_client.xml时,在同步调用配置的基础上,只需要修改referer的interface为Motan自动生成的接口类即可。
<motan:referer id="remoteService" interface="quickstart.FooServiceAsync" directUrl="localhost:8002"/>
- 异步使用方式如下:
public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {"classpath:motan_client.xml"}); FooServiceAsync service = (FooServiceAsync) ctx.getBean("remoteService"); // sync call System.out.println(service.hello("motan")); // async call ResponseFuture future = service.helloAsync("motan async "); System.out.println(future.getValue()); // multi call ResponseFuture future1 = service.helloAsync("motan async multi-1"); ResponseFuture future2 = service.helloAsync("motan async multi-2"); System.out.println(future1.getValue() ", " future2.getValue()); // async with listener FutureListener listener = new FutureListener() { @Override public void operationComplete(Future future) throws Exception { System.out.println("async call " (future.isSuccess() ? "sucess! value:" future.getValue() : "fail! exception:" future.getException().getMessage())); } }; ResponseFuture future3 = service.helloAsync("motan async multi-1"); ResponseFuture future4 = service.helloAsync("motan async multi-2"); future3.addListener(listener); future4.addListener(listener); }
具体代码可以参考demo模块
集群调用示例
在集群环境下使用Motan需要依赖外部服务发现组件,目前支持consul或zookeeper。
使用Consul作为注册中心
Consul安装与启动
安装(官方文档)
# 这里以linux为例 wget https://releases.hashicorp.com/consul/0.6.4/consul_0.6.4_linux_amd64.zip unzip consul_0.6.4_linux_amd64.zip sudo mv consul /bin
启动(官方文档)
测试环境启动: consul agent -dev
ui后台 http://localhost:8500/ui
Motan-Consul配置
- 在server和client中添加motan-registry-consul依赖
<dependency> <groupId>com.weibo</groupId> <artifactId>motan-registry-consul</artifactId> <version>RELEASE</version> </dependency>
- 在server和client的配置文件中分别增加consul registry定义。
<motan:registry regProtocol="consul" name="my_consul" address="127.0.0.1:8500"/>
- 在Motan client及server配置改为通过registry服务发现。
- client
<motan:referer id="remoteService" interface="quickstart.FooService" registry="my_consul"/>
- server
<motan:service interface="quickstart.FooService" ref="serviceImpl" registry="my_consul" export="8002" />
- server程序启动后,需要显式调用心跳开关,注册到consul。
MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true)
- 进入ui后台查看服务是否正常提供调用
- 启动client,调用服务
使用ZooKeeper作为注册中心
ZooKeeper安装与启动(官方文档)
单机版安装与启动
- Step2:
- 目标流量的RPC分组列表中选择目标流量分组,如motan-demo-rpc2,
- 流量权重分配中根据需要按比例分配(可选范围是[0,100]),这里输入0和1,表示将来自motan-demo-rpc的流量全部转入motan-demo-rpc2,点击Next
- Step3:(可选)若需根据具体IP调整流量,可在此配置
- RPC Client中输入来源流量的ip,RPC Server中输入目标流量的ip,点击添加后将在路由规则结果中显示
- 也可在路由规则结果中手动输入路由规则,路由规则见路由规则语法,点击Next
- Step4:指令预览
- 功能暂未启用,点击Finish完成流量切换操作
服务名语法
- 类名支持[a-zA-Z0-9_$.*]
- 运算符支持 () ! & |,优先级由高到低
- 复杂示例如下
(com.weibo.User* & !com.weibo.UserMapping) | com.weibo.Status* # 匹配com.weibo下以User开头的不包括UserMapping的所有服务,或以Status开头的所有服务
路由规则语法
- 必须包含to关键字,to左右两边分别为rpc client和rpc server的ip表达式,示例如下
* to 10.75.1.* 10.75.2.* to 10.73.1.* * to !10.75.1.1
指令管理
对注册中心下的所有指令信息进行增删改查操作
步骤:
- 在导航栏选择指令查询,进入指令查询页面
- 指令修改和删除操作需要管理员权限
操作记录查询(需要管理员权限)
查询指令增删改查记录
步骤:
- 在导航栏选择操作记录查询,进入操作记录查询
免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com