[RPC] Motan quick start

Article directory

  • I. Overview
  • 2. Function
  • 3. XML configuration usage
    • 1. Synchronous call
      • 1.1. Add dependencies in pom
      • 1.2. Create a public interface for the caller and server.
      • 1.3. Write business interface logic, create and start RPC Server.
      • 1.4. Create and execute RPC Client.
    • 2. Asynchronous call
      • 2.1. Add @MotanAsync annotation to the interface class
      • 2.2. When configuring motan_client.xml on the client side, based on the synchronous call configuration, you only need to modify the referer interface to the interface class automatically generated by Motan.
    • 3. Zookeeper registration center configuration
      • 3.1 Add maven dependencies in server and client
      • 3.2 Add the zookeeper registry definition to the server and client configuration files respectively.
      • 3.3 Change the Motan client and server configuration to discovery through the registry service.
      • 3.4 After the server program is started, you need to explicitly call the heartbeat switch and register it with zookeeper.
      • 3.5 Start the client and call the service
  • 4. Annotation configuration usage
    • Server side configuration
      • 1. Declare Annotation to specify the package name that needs to be parsed.
      • 2. Configure the bean objects of ProtocolConfig, RegistryConfig, and BasicServiceConfig
      • 3. Add the @MotanService annotation to the service implementation class, and the annotated configuration parameters are consistent with the service tag in the xml configuration method.
      • 4. Use spring-boot to start the service
    • client configuration
      • 1. Declare the configuration beans of Annotation, protocolConfig, and RegistryConfig.
      • 2. Configure basicRefererConfig bean
      • 3. Add the @MotanReferer annotation on the object using motan service.
      • 4. Use spring-boot to start the client

1. Overview

Motan is a high-performance, easy-to-use distributed remote service call (RPC) framework.

2. Function

Supports integration through spring configuration, providing distributed calling capabilities for services without writing additional code.
Supports the integration of configuration service components such as consul and zookeeper to provide service discovery and governance capabilities in cluster environments.
Supports advanced service scheduling capabilities such as dynamically customized load balancing and cross-machine room traffic adjustment.
Optimize based on high concurrency and high load scenarios to ensure high availability of RPC services in production environments.
Document index

3. XML configuration usage

1. Synchronous call

1.1, add dependencies in 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>

1.2. Create a public interface for the caller and server.

package quickstart;

public interface FooService {<!-- -->
    public String hello(String name);
}

1.3. Write business interface logic, create and start RPC Server.

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 implementation 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...");
    }
}

Executing the main function in the Server class will start the Motan service and listen to port 8002.

1.4. Create and execute 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"));
    }
}

2. Asynchronous call

The basic configuration of asynchronous calls is exactly the same as that of synchronous calls. You only need to add the @MotanAsync annotation to the interface class, and then make slight modifications on the client side. No modifications are required on the server side. Specific steps are as follows:

2.1. Add @MotanAsync annotation to the interface class

package quickstart;

@MotanAsync
public interface FooService {<!-- -->
    public String hello(String name);
}

When compiling,
Motan automatically generates an asynchronous service class. The generation path is target/generated-sources/annotations/. The generated class name is the service name plus Async.
For example, the service class name is FooService.java, and the automatically generated class name is FooServiceAsync.java.
In addition, the path of motan’s automatically produced class files needs to be configured as the project source path. You can use the maven plugin or configure it manually.
The pom.xml configuration is as follows:

<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. When configuring motan_client.xml on the client side, based on the synchronous call configuration, you only need to modify the referer’s interface to the interface class automatically generated by Motan.

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

Asynchronous usage is as follows:

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 registration center configuration

3.1 Add maven dependencies in server and client

<dependency>
    <groupId>com.weibo</groupId>
    <artifactId>motan-registry-zookeeper</artifactId>
    <version>RELEASE</version>
</dependency>

3.2 Add zookeeper registry definitions to the server and client configuration files respectively

<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 Change the Motan client and server configuration to discovery through the registry service.

client

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

server

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

After the 3.4 server program is started, you need to explicitly call the heartbeat switch and register it with zookeeper.

MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true)

3.5 Start the client and call the service

4. Annotation configuration usage

Server side configuration

1. Declare Annotation to specify the package name that needs to be parsed

 @Bean
 public AnnotationBean motanAnnotationBean() {<!-- -->
     AnnotationBean motanAnnotationBean = new AnnotationBean();
     motanAnnotationBean.setPackage("com.weibo.motan.demo.server");
     return motanAnnotationBean;
 }

2. Configure the bean objects of ProtocolConfig, RegistryConfig, and BasicServiceConfig

The functions are consistent with the protocol, registry, and basicService tags in the xml configuration.

 @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. Add the @MotanService annotation to the service implementation class, and the annotated configuration parameters are consistent with the service tag in the xml configuration method.

 @MotanService(export = "demoMotan:8002")
 public class MotanDemoServiceImpl implements MotanDemoService {<!-- -->

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

4. Use spring-boot to start the service

 @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 configuration

1. Declare the configuration beans of Annotation, protocolConfig, and RegistryConfig.

The method is similar to the server-side configuration.

2. Configure 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;
 }

3. Add the @MotanReferer annotation on the object using motan service,

The registration configuration is consistent with the referer tag in xml mode

 @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. Use spring-boot to start the client

 @EnableAutoConfiguration
 @SpringBootApplication
 public class SpringBootRpcClientDemo {<!-- -->

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

Official website document