• [RPC] Motan快速开始


    一、概述

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

    二、功能

    支持通过spring配置方式集成,无需额外编写代码即可为服务提供分布式调用能力。
    支持集成consul、zookeeper等配置服务组件,提供集群环境的服务发现及治理能力。
    支持动态自定义负载均衡、跨机房流量调整等高级服务调度能力。
    基于高并发、高负载场景进行优化,保障生产环境下RPC服务高可用。
    文档索引

    三、XML配置使用

    1、同步调用

    1.1、pom中添加依赖

    <dependency>
         <groupId>com.weibogroupId>
         <artifactId>motan-coreartifactId>
         <version>RELEASEversion>
     dependency>
     <dependency>
         <groupId>com.weibogroupId>
         <artifactId>motan-transport-nettyartifactId>
         <version>RELEASEversion>
     dependency>
     
     
     <dependency>
         <groupId>com.weibogroupId>
         <artifactId>motan-springsupportartifactId>
         <version>RELEASEversion>
     dependency>
     <dependency>
         <groupId>org.springframeworkgroupId>
         <artifactId>spring-contextartifactId>
         <version>4.2.4.RELEASEversion>
     dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

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

    package quickstart;
    
    public interface FooService {
        public String hello(String name);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    package quickstart;
    
    public class FooServiceImpl implements FooService {
    
        public String hello(String name) {
            System.out.println(name + " invoked rpc service");
            return "hello " + name;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    src/main/resources/motan_server.xml

    
    <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">
    
        
        <bean id="serviceImpl" class="quickstart.FooServiceImpl" />
        
        <motan:service interface="quickstart.FooService" ref="serviceImpl" export="8002" />
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    执行Server类中的main函数将会启动Motan服务,并监听8002端口.

    1.4、创建并执行RPC Client。

    src/main/resources/motan_client.xml

    
    <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">
    
        
        <motan:referer id="remoteService" interface="quickstart.FooService" directUrl="localhost:8002"/>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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"));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2、异步调用

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

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

    package quickstart;
    
    @MotanAsync
    public interface FooService {
        public String hello(String name);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    编译时,
    Motan自动生成异步service类,生成路径为target/generated-sources/annotations/,生成的类名为service名加上Async。
    例如 service类名为FooService.java,则自动生成的类名为FooServiceAsync.java。
    另外,需要将motan自动生产类文件的路径配置为项目source path,可以使用maven plugin或手动配置。
    pom.xml配置如下:

    <plugin>
        <groupId>org.codehaus.mojogroupId>
        <artifactId>build-helper-maven-pluginartifactId>
        <version>RELEASEversion>
        <executions>
            <execution>
                <phase>generate-sourcesphase>
                <goals>
                    <goal>add-sourcegoal>
                goals>
                <configuration>
                    <sources>
                        <source>${project.build.directory}/generated-sources/annotationssource>
                    sources>
                configuration>
            execution>
        executions>
    plugin>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

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

    <motan:referer id="remoteService" interface="quickstart.FooServiceAsync" directUrl="localhost:8002"/>
    
    • 1

    异步使用方式如下:

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    3、Zookeeper注册中心配置

    3.1 在server和client中 添加maven依赖

    <dependency>
        <groupId>com.weibogroupId>
        <artifactId>motan-registry-zookeeperartifactId>
        <version>RELEASEversion>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    <motan:registry regProtocol="zk" name="my_zookeeper" address="127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183"/>
    
    • 1

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

    client

    <motan:referer id="remoteService" interface="quickstart.FooService" registry="my_zookeeper"/>
    
    • 1

    server

    <motan:service interface="quickstart.FooService" ref="serviceImpl" registry="my_zookeeper" export="8002" />
    
    • 1

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

    MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true)
    
    • 1

    3.5 启动client,调用服务


    四、注解配置使用

    server端配置

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

     @Bean
     public AnnotationBean motanAnnotationBean() {
         AnnotationBean motanAnnotationBean = new AnnotationBean();
         motanAnnotationBean.setPackage("com.weibo.motan.demo.server");
         return motanAnnotationBean;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

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

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

     @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;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

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

     @MotanService(export = "demoMotan:8002")
     public class MotanDemoServiceImpl implements MotanDemoService {
    
         public String hello(String name) {
             System.out.println(name);
             return "Hello " + name + "!";
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4、使用spring-boot启动服务

     @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...");
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    client端配置

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

    方式与server端配置类似。

    2、配置basicRefererConfig bean

     @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;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

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

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

     @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;
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    4、使用spring-boot启动client

     @EnableAutoConfiguration
     @SpringBootApplication
     public class SpringBootRpcClientDemo {
    
         public static void main(String[] args) {
             SpringApplication.run(SpringBootRpcClientDemo.class, args);
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    官网文档

  • 相关阅读:
    SQL 入门指南:从零开始学习 SQL
    《Python+Kivy(App开发)从入门到实践》自学笔记:简单UX部件——Video视频
    神经网络模型如何使用的,神经网络模型是干嘛的
    【MATLAB 入门手册】基本操作与矩阵输入
    【SpringBoot】68、SpringBoot解决HttpServletRequest中输入流不能重复读的问题
    如何用jxTMS开发一个功能(五)
    运维监控背景信息
    【SA8295P 源码分析 (三)】108 - QNX AIS Camera 如何在各个环节 Dump 摄像头Raw Data(含代码追踪分析全过程)
    TCP / UDP 概念 + 实验(计网自顶向下)
    7 张图解 CrashLoopBackOff,如何发现问题并解决它?
  • 原文地址:https://blog.csdn.net/malu_record/article/details/134005444