[RPC] Motan快速开始

文章目录

一、概述

Motan是一套高性能、易于使用的分布式远程服务调用(RPC)框架。

二、功能

支持通过spring配置方式集成,无需额外编写代码即可为服务提供分布式调用能力。

支持集成consul、zookeeper等配置服务组件,提供集群环境的服务发现及治理能力。

支持动态自定义负载均衡、跨机房流量调整等高级服务调度能力。

基于高并发、高负载场景进行优化,保障生产环境下RPC服务高可用。

文档索引

三、XML配置使用

1、同步调用

1.1、pom中添加依赖

xml 复制代码
<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>

1.2、为调用方和服务方创建公共接口。

java 复制代码
package quickstart;

public interface FooService {
    public String hello(String name);
}

1.3、编写业务接口逻辑、创建并启动RPC Server。

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 复制代码
<?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

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端口.

1.4、创建并执行RPC Client。

src/main/resources/motan_client.xml

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

xml 复制代码
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"));
    }
}

2、异步调用

异步调用与同步调用基本配置完全一样,只需要在接口类中加上@MotanAsync注解,然后client端稍作修改。server端不需要做任何修改。具体步骤如下:

2.1、在接口类上加@MotanAsync注解

java 复制代码
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配置如下:

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>

2.2、在client端配置motan_client.xml时,在同步调用配置的基础上,只需要修改referer的interface为Motan自动生成的接口类即可。

xml 复制代码
<motan:referer id="remoteService" interface="quickstart.FooServiceAsync" directUrl="localhost:8002"/>

异步使用方式如下:

java 复制代码
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);
}

3、Zookeeper注册中心配置

3.1 在server和client中 添加maven依赖

xml 复制代码
<dependency>
    <groupId>com.weibo</groupId>
    <artifactId>motan-registry-zookeeper</artifactId>
    <version>RELEASE</version>
</dependency>

3.2 在server和client 的配置文件中分别增加zookeeper registry定义

xml 复制代码
<motan:registry regProtocol="zk" name="my_zookeeper" address="127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183"/>

3.3 在Motan client及server配置改为通过registry服务发现。

client

xml 复制代码
<motan:referer id="remoteService" interface="quickstart.FooService" registry="my_zookeeper"/>

server

xml 复制代码
<motan:service interface="quickstart.FooService" ref="serviceImpl" registry="my_zookeeper" export="8002" />

3.4 server程序启动后,需要显式调用心跳开关,注册到zookeeper。

xml 复制代码
MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true)

3.5 启动client,调用服务


四、注解配置使用

server端配置

1、声明Annotation用来指定需要解析的包名

java 复制代码
 @Bean
 public AnnotationBean motanAnnotationBean() {
     AnnotationBean motanAnnotationBean = new AnnotationBean();
     motanAnnotationBean.setPackage("com.weibo.motan.demo.server");
     return motanAnnotationBean;
 }

2、配置ProtocolConfig、RegistryConfig、BasicServiceConfig的bean对象

功能与xml配置中的protocol、registry、basicService标签一致。

java 复制代码
 @Bean(name = "demoMotan")
 public ProtocolConfigBean protocolConfig1() {
     ProtocolConfigBean config = new ProtocolConfigBean();
     config.setDefault(true);
     config.setName("motan");
     config.setMaxContentLength(1048576);
     return config;
 }

 @Bean(name = "registryConfig1")
 public RegistryConfigBean registryConfig() {
     RegistryConfigBean config = new RegistryConfigBean();
     config.setRegProtocol("local");
     return config;
 }

 @Bean
 public BasicServiceConfigBean baseServiceConfig() {
     BasicServiceConfigBean config = new BasicServiceConfigBean();
     config.setExport("demoMotan:8002");
     config.setGroup("testgroup");
     config.setAccessLog(false);
     config.setShareChannel(true);
     config.setModule("motan-demo-rpc");
     config.setApplication("myMotanDemo");
     config.setRegistry("registryConfig1");
     return config;
 }

3、service的实现类上添加@MotanService注解,注解的配置参数与xml配置方式的service标签一致。

java 复制代码
 @MotanService(export = "demoMotan:8002")
 public class MotanDemoServiceImpl implements MotanDemoService {

     public String hello(String name) {
         System.out.println(name);
         return "Hello " + name + "!";
     }
 }

4、使用spring-boot启动服务

java 复制代码
 @EnableAutoConfiguration
 @SpringBootApplication
 public class SpringBootRpcServerDemo {

     public static void main(String[] args) {
         System.setProperty("server.port", "8081");
         ConfigurableApplicationContext context =  SpringApplication.run(SpringBootRpcServerDemo.class, args);
		 MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true);
         System.out.println("server start...");
     }
 }

client端配置

1、声明Annotation、protocolConfig、RegistryConfig的配置bean。

方式与server端配置类似。

2、配置basicRefererConfig bean

java 复制代码
 @Bean(name = "motantestClientBasicConfig")
 public BasicRefererConfigBean baseRefererConfig() {
     BasicRefererConfigBean config = new BasicRefererConfigBean();
     config.setProtocol("demoMotan");
     config.setGroup("motan-demo-rpc");
     config.setModule("motan-demo-rpc");
     config.setApplication("myMotanDemo");
     config.setRegistry("registry");
     config.setCheck(false);
     config.setAccessLog(true);
     config.setRetries(2);
     config.setThrowException(true);
     return config;
 }

3、在使用motan service 的对象上添加@MotanReferer注解,

注册配置与xml方式的referer标签一致

java 复制代码
 @RestController
 public class HelloController {

     @MotanReferer(basicReferer = "motantestClientBasicConfig", group = "testgroup", directUrl = "127.0.0.1:8002")
     MotanDemoService service;

     @RequestMapping("/")
     @ResponseBody
     public String home() {
         String result = service.hello("test");
         return result;
     }
 }

4、使用spring-boot启动client

java 复制代码
 @EnableAutoConfiguration
 @SpringBootApplication
 public class SpringBootRpcClientDemo {

     public static void main(String[] args) {
         SpringApplication.run(SpringBootRpcClientDemo.class, args);
     }
 }

官网文档

相关推荐
眠りたいです3 天前
基于脚手架微服务的视频点播系统-脚手架开发部分-brpc中间件介绍与使用及二次封装
c++·微服务·中间件·rpc·架构·brpc
锋风Fengfeng4 天前
基于Binder的4种RPC调用
网络协议·rpc·binder
编啊编程啊程4 天前
gRPC从0到1系列【20】
java·rpc·kafka·dubbo·nio
编啊编程啊程4 天前
gRPC从0到1系列【19】
java·spring boot·rpc·dubbo·nio
寒士obj5 天前
轻量级、高性能的RPC框架——Dubbo
网络协议·rpc·dubbo
失散135 天前
分布式专题——26 BIO、NIO编程与直接内存、零拷贝深入辨析
java·分布式·rpc·架构·nio·零拷贝
编啊编程啊程9 天前
gRPC从0到1系列【6】
java·rpc·kafka·dubbo·nio
她说人狗殊途10 天前
Spring IoC容器加载过程 vs Bean生命周期对应关系图
java·开发语言·rpc
weixin_4462608510 天前
提升开发效率的RPC系统!
网络·网络协议·rpc
H3C-Navigator11 天前
RPC在分布式存储系统中的应用
分布式·网络协议·rpc