zoukankan      html  css  js  c++  java
  • 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.运行结果

     

  • 相关阅读:
    设计模式七大原则之单一职责原则
    机器学习入门与进阶
    Django之路
    Python编程之路
    Python练习1
    Docker入门与进阶
    运维相关
    Node.js(一)
    位运算
    双指针算法
  • 原文地址:https://www.cnblogs.com/IT_CH/p/12702226.html
Copyright © 2011-2022 走看看