[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);
     }
 }

官网文档

相关推荐
笨鸟先飞的橘猫1 天前
skynet——RPC 超时机制优化方案
游戏·rpc·skynet
9624562 天前
Go EVM 链上数据平台实践:从 RPC Demo 到可演进架构
rpc·架构·golang
普通人63 天前
php+html+canvas实现树状打开的结构
开发语言·javascript·html5·1024程序员节
打工仔折腾 AI4 天前
用 Dashlet 把极空间 NAS 服务入口整理成统一导航首页的实践
java·开发语言·人工智能·后端·python·rpc·ai agent 实战
小楼昨夜又东风1265 天前
一文理清K8s PVC挂载完整流程
容器·rpc·kubernetes
青柠之夏cc5 天前
Laravel服务容器底层原理揭秘
javascript·rpc·laravel
普通人66 天前
宝塔中实现按地区过滤和官网跳转伪静态
服务器·开发语言·nginx·1024程序员节
普通人66 天前
php处理百度编辑器有误html
开发语言·编辑器·html·php·1024程序员节
墨神谕9 天前
RPC框架与HTTP REST的区别
网络协议·http·rpc
殷色玫瑰10 天前
C++ STL:map 与 set 详解——从底层红黑树到实际应用
c语言·数据结构·c++·算法·visualstudio·rpc