zoukankan      html  css  js  c++  java
  • Avro实现RPC

    一、什么是RPC?

    1. RPC 的全称是 Remote Procedure Call(远程过程调用)是一种进程间通信方式
    2. 它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。 即程序员无论是调用本地的还是远程的,本质上编写的调用代码基本相同

    二、特点

    1. 简单:RPC 概念的语义十分清晰和简单,这样建立分布式计算就更容易
    2. 高效:过程调用看起来十分简单而且高效
    通用:在单机计算中过程往往是不同算法部分间最重要的通信机制。 通俗一点说,就是一般程序员对于本地的过程调用很熟悉,那么我们在通过网络做远程通信时,通过RPC 把远程调用做得和本地调用完全类似,那么就更容易被接受,使用起来也就毫无障碍。

    三、RPC架构

    1. 用户(User)
    2. 用户存根(User-Stub)
    3. RPC通信包(称为RPCRuntime)
    4. 服务器存根(Server-Stub)
    服务器(Server)
    客户端(client)

    3.1 框架特点

    1. 基于RPC的进程通信方式
    2. 有自定义的一套序列化和反序列的机制
    3. 客户端通过代理机制调用远程方法
    服务端通过回调机制执行方法及返回结果

    四、基本过程

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

    五、创建maven项目,准备pom.xml文件

    <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</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <dependencies>
            <dependency>
                <groupId>org.apache.avro</groupId>
                <artifactId>avro</artifactId>
                <version>1.8.2</version>
            </dependency>
            <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.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <!-- 一般而言,target与source是保持一致的,但是,有时候为了让程序能在其他版本的jdk中运行(对于低版本目标jdk,源代码中不能使用低版本jdk中不支持的语法),会存在target不同于source的情况 -->
                        <source>1.8</source> <!-- 源代码使用的JDK版本 -->
                        <target>1.8</target> <!-- 需要生成的目标class文件的编译版本 -->
                        <encoding>UTF-8</encoding><!-- 字符集编码 -->
                    </configuration>
    
                </plugin>
                <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>
        </build>
    </project>

    六、在指定的目录下编辑avdl文件

    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.blb")
     protocol AddService{
     import schema "user.avsc";
     int add(int x , int y);
     void parseUser(com.blb.User user);
     }

    七、生成接口类

     八、实现服务端接口

    import com.blb.AddService;
    import com.blb.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;
        }
    }

    8.1 先实现服务器端

    import com.blb.AddService;
    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(8888));
        }
    }

    8.2再实现客户端

    import com.blb.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",8888));
            //--因为接口不能直接使用,avro底层是通过jdk动态代理生成接口的代理对象
            AddService proxy = SpecificRequestor.getClient(AddService.class,client);
    
            int result = proxy.add(2,3);
            System.out.println("客户端收到结果:"+result);
        }

    九、结果展示

  • 相关阅读:
    看过设计模式第一章的心得
    支付宝支付过程填坑
    C# 合并只要有交集的所有集合
    C#中的反射 Reflection
    动态更改配置文件
    六种弹窗
    Respone弹窗
    Aspose是一个很强大的控件,可以用来操作word,excel,ppt等文件
    使用ECharts报表统计公司考勤加班,大家加班多吗?
    排污许可管理条例-中华人民共和国国务院令第736号
  • 原文地址:https://www.cnblogs.com/the-roc/p/12711012.html
Copyright © 2011-2022 走看看