IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Nacos源码系列之Java实现grpc(四) -> 正文阅读

[网络协议]Nacos源码系列之Java实现grpc(四)

Java实现grpc

1、实践

(1) IDEA安装插件

Protobuf Support
在这里插入图片描述

(2) 新建.proto文件

我这里命名为test.proto。
指定生成代码的包路径、接口服务等。
定义了一个UserService服务,包含一个方法getUser()。以及请求类UserRequest、响应类UserReply。



syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples";
option java_outer_classname = "UserProto";
option objc_class_prefix = "HLW";

package test;

// The user service definition.
service User {
    // getUser method
    rpc getUser (UserRequest) returns (UserReply) {}
}

// The request message containing the user's name.
message UserRequest {
    string name = 1;
}

// The response message containing the user
message UserReply {
    string message = 1;
}

(3) pom引入依赖

包括grpc、protobuf和protobuf插件。



    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <protobuf.version>3.6.1</protobuf.version>
        <grpc.version>1.19.0</grpc.version>
    </properties>

    <dependencies>
     <dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java</artifactId>
        <version>${protobuf.version}</version>
    </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty</artifactId>
            <version>${grpc.version}</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>${grpc.version}</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>${grpc.version}</version>
        </dependency>
    </dependencies>

    <build>
    <extensions>
        <extension>
            <groupId>kr.motd.maven</groupId>
            <artifactId>os-maven-plugin</artifactId>
            <version>1.5.0.Final</version>
        </extension>
    </extensions>
    <plugins>
        <!--protobuf插件-->
        <plugin>
            <groupId>org.xolstice.maven.plugins</groupId>
            <artifactId>protobuf-maven-plugin</artifactId>
            <version>0.5.0</version>
            <configuration>
                <!--
                  The version of protoc must match protobuf-java. If you don't depend on
                  protobuf-java directly, you will be transitively depending on the
                  protobuf-java version that grpc depends on.
                -->
                <protocArtifact>
                    com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}
                </protocArtifact>
                <pluginId>grpc-java</pluginId>
                <pluginArtifact>
                    io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
                </pluginArtifact>
            </configuration>
        </plugin>
    </plugins>
</build>

(4) 生成代码

操作protobuf插件的compile、compile-custom命令。

在这里插入图片描述

生成的代码如下,包含:
● protoc-dependencies: 相关依赖,proto文件格式。
● protoc-plugins: pom中指定的插件。
● generated-sources: 生成的源码包文件。

(5) 创建服务端

Server端要提供一个查询服务,需要继承UserGrpc.UserImplBase。示例中,监听端口10001。
public class TestService extends UserGrpc.UserImplBase{

public void getUser(UserRequest request,
                        StreamObserver<UserReply> responseObserver) {
        UserReply reply = UserReply.newBuilder().setMessage("this is "+request.getName()).build();
        responseObserver.onNext(reply);
        responseObserver.onCompleted();
    }
}
public class UserServer {
    private Server server;

    public static void main(String[] args) throws InterruptedException, IOException {
        UserServer server=new UserServer();
        server.start();
        server.blockUntilShutdown();
    }
    private void start() throws IOException {
        int port=10001;
        server= ServerBuilder.forPort(port)
                .addService(new TestService())
                .build().start();
        System.out.println("server start..... listen on "+port);
        Runtime.getRuntime().addShutdownHook(new Thread(()->{
            System.out.println("shut down grpc server");
            try {
                UserServer.this.stop();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }));
    }

    private void stop() throws InterruptedException {
        if(server!=null){
            server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
        }
    }

    private void blockUntilShutdown() throws InterruptedException {
        if(server!=null){
            server.awaitTermination();
        }
    }
}

(6) 创建客户端

客户端这里要远程调用服务端的接口,因为是本地模拟,所以ip:127.0.0.1 port:10001。
通过Stub,像调用本地方法一样调用远程方法。

public class UserClient {
    private ManagedChannel channel;

    private UserGrpc.UserBlockingStub stub;

    public UserClient(String host,int port){
        channel= ManagedChannelBuilder.forAddress(host,port).usePlaintext().build();
        stub=UserGrpc.newBlockingStub(channel);
    }

    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }

    public String getUser(String name){
        UserRequest request = UserRequest.newBuilder().setName(name).build();
        UserReply helloReply = stub.getUser(request);
        return helloReply.getMessage();
    }

    public static void main(String[] args) throws InterruptedException {
        UserClient client=new UserClient("127.0.0.1",10001);
        String hello = client.getUser("hello");
        System.out.println("client:"+hello);
        client.shutdown();
    }
}

(7) 测试

因为我们是服务端监听客户端,所以要先启动服务端,再启动客户端。
在这里插入图片描述

2、源码

(1) protobuf

protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,可用于数据通信协议和数据存储等,它是 Google 提供的一个具有高效协议数据交换格式工具库,是一种灵活、高效和自动化机制的结构数据序列化方法。

特点:二进制方式来表示数据。

相比XML,有编码后体积更小,编解码速度更快的优势;相比于 Json,Protobuf 有更高的转化效率,时间效率和空间效率都是 JSON 的 3-5 倍。

(2) 重要类和接口

针对上面生成的几个类和接口,做详细的说明:
在这里插入图片描述

我们先介绍通过compile命令生成的java包下的类:

UserRequestOrBuilder:
用户服务的响应接口,getName()对应proto文件中的UserRequest的name字符串的get操作。

//proto
message UserRequest {
    string name = 1;
}
public interface UserRequestOrBuilder extends
    // @@protoc_insertion_point(interface_extends:test.UserRequest)
    com.google.protobuf.MessageOrBuilder {

  /**
   * <code>string name = 1;</code>
   */
  java.lang.String getName();
  /**
   * <code>string name = 1;</code>
   */
  com.google.protobuf.ByteString
      getNameBytes();
}

UserRequest:
封装的UserService的请求实体。
继承GeneratedMessageV3类,并实现UserRequestOrBuilder接口。
内部类Builder可以做参数处理,并对getName()的具体实现逻辑。

public  final class UserRequest extends
    com.google.protobuf.GeneratedMessageV3 implements
    // @@protoc_insertion_point(message_implements:test.UserRequest)
    UserRequestOrBuilder {
    
      public static final class Builder extends
      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
      // @@protoc_insertion_point(builder_implements:test.UserRequest)
      io.grpc.examples.UserRequestOrBuilder {
             public Builder setName(java.lang.String value) {
                  if (value == null) {
                    throw new NullPointerException();
                  }
  
                  name_ = value;
                  onChanged();	
                  return this;
            }
            public java.lang.String getName() {
              java.lang.Object ref = name_;
              if (!(ref instanceof java.lang.String)) {
                com.google.protobuf.ByteString bs =(com.google.protobuf.ByteString) ref;
                java.lang.String s = bs.toStringUtf8();
                name_ = s;
                return s;
              } else {
                return (java.lang.String) ref;
              }
           }
      }
}

UserReplyOrBuilder:
用户服务的响应接口,getMessage()对应proto文件中的UserReply的message字符串的get操作。

//proto
message UserReply {
    string message = 1;
}
//UserReplyOrBuilder接口
public interface UserReplyOrBuilder extends
    // @@protoc_insertion_point(interface_extends:test.UserReply)
    com.google.protobuf.MessageOrBuilder {

  /**
   * <code>string message = 1;</code>
   */
  java.lang.String getMessage();
  /**
   * <code>string message = 1;</code>
   */
  com.google.protobuf.ByteString
      getMessageBytes();
}

UserResponse:
封装请求的响应实体。对getMessage()的具体实现。
与UserRequest类似,也有一个内部类Builder。

UserGrpc:
通过命令compile-custom生成。是grpc的核心类。
提供了三种场景的stub实现:UserStub(async)、UserBlockingStub(block)、UserFutureStub(ListenableFuture)

在这里插入图片描述

下一篇介绍Nacos中的grpc应用。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-04-18 18:20:11  更:2022-04-18 18:22:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:26:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码