Avro实现RPC

Posted it_ch

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Avro实现RPC相关的知识,希望对你有一定的参考价值。

RPC是什么?

  • RPC是指远程过程调用【是一种进程间的通信方式】
  • 例如两台服务器A,B,一个应用部署在A上面,A想要调B服务器上的函数或者方法,由于不在一个内存空间,不能直接调用,需要通过网络来传达调用的数据

RPC的特点?

  • 简单:语义清晰简单,建立分布式计算更加容易
  • 高效:远程调用简单高效
  • 通用:RPC把远程调用做的和本地调用完全类似,那么就容易被接受,使用起来也没有障碍

RPC架构?

1)用户(User)

2)用户存根(User-Stub)

3)RPC通信包(被称为RPCRuntime)

4)服务器存根(Server)

5)服务器(Server)

技术图片

 当用户发起一个远程CALL的时候,远程如下:

  1. 服务消费方(User)调用以本地方式调用服务;
  2. User-stub(存根)接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体,并交给RPCRuntime模块
  3. RPCRuntime找到服务地址,并将消息发送到服务端
  4. 服务端的RPCRuntime收到消息后,传给Server-stub
  5. Server-stub根据解码结果调用本地的服务
  6. 本地服务执行并将结果返回给Server-stub
  7. server stub将返回结果打包成消息并发送至消费方
  8. client stub接收到消息,并进行解码
  9. 服务消费方得到最终结果

实现步骤

1.创建maven工程,导入pom依赖

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.blb</groupId>
  <artifactId>Avro_RPC</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>Avro_RPC</name>
  <!-- FIXME change it to the project‘s website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.avro/avro -->
    <dependency>
      <groupId>org.apache.avro</groupId>
      <artifactId>avro</artifactId>
      <version>1.8.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.avro/avro-tools -->
    <dependency>
      <groupId>org.apache.avro</groupId>
      <artifactId>avro-tools</artifactId>
      <version>1.8.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.avro</groupId>
      <artifactId>avro-maven-plugin</artifactId>
      <version>1.8.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.avro</groupId>
      <artifactId>avro-compiler</artifactId>
      <version>1.8.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.avro</groupId>
      <artifactId>avro-ipc</artifactId>
      <version>1.8.2</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.avro</groupId>
        <artifactId>avro-maven-plugin</artifactId>
        <version>1.8.2</version>
        <executions>
          <execution>
            <phase>generate-sources</phase>
            <goals>
              <goal>schema</goal>
            </goals>
            <configuration>
              <sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory>
              <outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

2.在指定目录下编辑acdl文件

a. 如果传递的是基本类型,则示例格式如下:

@namespace("rpc.service")
protocol AddService{
int add(int i,int y);
}

b. 如果传递的是对象,则示例格式如下:

@namespace("rpc.service")
protocol TransferService{
import schema "User.avsc";
void parseUser(avro.domain.User user);
}

c. 如果传递的是map,并且map中包含对象,则示例格式如下:

@namespace("rpc.service")
protocol MapService{
import schema "User.avsc";
void parseUserMap(map<avro.domain.User> userMap);
}

d.这个是我们的User.avdl文件

@namespace("com.service")
protocol AddService{
import schema "user.avsc";
int add(int x , int y);
void parseUser(com.domain.User user);
}

3.根据avro插件生成文件对应的接口类

技术图片

 技术图片

4.实现服务器端接口

package com.blb.service;

import com.blb.pojo.User;
import org.apache.avro.AvroRemoteException;

public class AddServiceImpl implements AddService {
    @Override
    public int add(int x, int y) throws AvroRemoteException {
        System.out.println(x+y);
        return x+y;
    }

    @Override
    public Void parseUser(User user) throws AvroRemoteException {
        System.out.println(user);
        return null;
    }
}

5.实现服务器端

package com.blb.server;

import com.blb.service.AddService;
import com.blb.service.AddServiceImpl;
import org.apache.avro.ipc.NettyServer;
import org.apache.avro.ipc.specific.SpecificResponder;

import java.net.InetSocketAddress;

public class RPC_Server {

    public static void main(String[] args) {
        NettyServer server = new NettyServer(
                new SpecificResponder(AddService.class,new AddServiceImpl()),
                new InetSocketAddress(9999)
        );
        System.out.println("服务端启动");
    }
}

6.实现客户端

package com.blb.client;

import com.blb.service.AddService;
import org.apache.avro.ipc.NettyTransceiver;
import org.apache.avro.ipc.specific.SpecificRequestor;

import java.io.IOException;
import java.net.InetSocketAddress;

public class RPC_Client {

    public static void main(String[] args) throws IOException {
        NettyTransceiver client = new NettyTransceiver(
                new InetSocketAddress("127.0.0.1",9999)
        );
        //--因为接口不能直接使用,avro底层是通过jdk动态代理生成接口的代理对象
        AddService proxy = SpecificRequestor.getClient(AddService.class,client);
        int result = proxy.add(2,3);
        System.out.println("客户端收到结果:"+result);
    }

}

7.运行结果

技术图片 技术图片

 

以上是关于Avro实现RPC的主要内容,如果未能解决你的问题,请参考以下文章

avro序列化详细操作

Avro RPC实例

Avro RPC/Storm 集成

从 BigQuery 读取数据并将其写入云存储上的 avro 文件格式

dubbo/dubbox 增加原生thrift及avro支持

#yyds干货盘点# 基于Netty,20分钟手写一个RPC框架