热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

gRPC创建JavaRPC服务

1.说明本文介绍使用gRPC创建Java版本的RPC服务,包括通过.proto文件生成Java代码的方法,以及服务端和客户端代码使用示例。
1.说明

本文介绍使用gRPC创建Java版本的RPC服务,
包括通过.proto文件生成Java代码的方法,
以及服务端和客户端代码使用示例。

2.创建生成代码工程

创建Maven工程,grpc-compile。

2.1.修改pom.xml

引入生成代码需要的jar包依赖,
以及构建依赖配置:

io.grpcgrpc-protobuf1.32.1io.grpcgrpc-stub1.32.1kr.motd.mavenos-maven-plugin1.6.2org.xolstice.maven.pluginsprotobuf-maven-plugin0.6.1com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}grpc-javaio.grpc:protoc-gen-grpc-java:1.32.1:exe:${os.detected.classifier}compilecompile-custom

2.2.创建.proto文件

在srcmain下面新建proto目录,
在里面创建helloworld.proto文件:

// 显示声明使用proto3, 否则使用默认的proto2
syntax = "proto3";

// 生成类的包名
option java_package = "com.asiainfo.yuwen.grpc.helloworld";
// 生成类的文件名,否则默认生成的类名为proto文件名的驼峰命名
option java_outer_classname = "HelloWorldProto";
// 定义的所有消息、枚举和服务生成对应的多个类文件,而不是以内部类的形式出现
option java_multiple_files = false;

// greeting服务定义
service Greeter {
  // sayHello方法,格式为"方法名 请求参数 返回参数"
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  // 另一个sayHello方法
  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}

// 方法请求,包含用户名
message HelloRequest {
  string name = 1;
}

// 方法响应,包含响应的消息
message HelloReply {
  string message = 1;
}

2.3.生成Java代码

在grpc-compile下执行Maven编译命令:

mvn clean compile

会在target目录下生成代码:

gRPC创建Java RPC服务

主要关注generated-sources目录:
generated-sourcesprotobufgrpc-java目录下生成了
comasiainfoyuwengrpchelloworldGreeterGrpc.java;
generated-sourcesprotobufjava目录下生成了
comasiainfoyuwengrpchelloworldHelloWorldProto.java。

其中GreeterGrpc.java对应greeting服务定义,
如果有多个服务,会对应生成多个java类,
HelloWorldProto.java对应消息、枚举等对象的定义。
由于生成的代码内容太多了,这里就不贴出来了。

3.创建服务端工程

创建Maven工程,grpc-server。

3.1.修改pom.xml

引入使用gRPC需要依赖的jar包:

io.grpcgrpc-netty-shaded1.32.1io.grpcgrpc-protobuf1.32.1io.grpcgrpc-stub1.32.1

3.2.拷贝生成的代码

把上面生成的Java代码,
GreeterGrpc.java和HelloWorldProto.java,
拷贝到grpc-server的src/main/java目录下,
可以从com这一层目录开始拷贝,
这样就不用再手动创建包路径了。

3.3.创建greeting服务实现类

为了实现greeting服务定义的两个sayHello方法,
需要继承GreeterGrpc.GreeterImplBase接口,
创建实现类GreeterImpl.java:

package com.asiainfo.yuwen.grpc.helloworld.controller.impl;

import com.asiainfo.yuwen.grpc.helloworld.GreeterGrpc;
import com.asiainfo.yuwen.grpc.helloworld.HelloWorldProto.HelloReply;
import com.asiainfo.yuwen.grpc.helloworld.HelloWorldProto.HelloRequest;

import io.grpc.stub.StreamObserver;

/**
 * 
 * greeting服务实现类
 * 

*/
public class GreeterImpl extends GreeterGrpc.GreeterImplBase {

@Override
public void sayHello(HelloRequest req, StreamObserver responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}

@Override
public void sayHelloAgain(HelloRequest req, StreamObserver responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello again " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}

3.4.创建服务端启动类

为了对外提供gRPC服务,
需要创建服务端启动类GRPCServer.java:

package com.asiainfo.yuwen.grpc.server;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import com.asiainfo.yuwen.grpc.helloworld.controller.impl.GreeterImpl;

import io.grpc.Server;
import io.grpc.ServerBuilder;

/**
 * gRPC服务启动类,启动时注册添加需要对外提供的服务类
 */
public class GRPCServer {

    private Server server;

    private void start() throws IOException {
        // 服务运行端口
        int port = 50051;
        // 注册对外提供的服务
        server = ServerBuilder.forPort(port).addService(new GreeterImpl()).build().start();
        System.out.println("Server started, listening on " + port);

        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                // 使用标准错误输出,因为日志记录器有可能在JVM关闭时被重置
                System.err.println("*** shutting down gRPC server since JVM is shutting down");
                try {
                    GRPCServer.this.stop();
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
                System.err.println("*** server shut down");
            }
        });
    }

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

    /**
     * 在主线程上等待终止,因为grpc库使用守护进程。
     */
    private void blockUntilShutdown() throws InterruptedException {
        if (server != null) {
            server.awaitTermination();
        }
    }

    /**
     * 启动服务Main方法
     */
    public static void main(String[] args) throws IOException, InterruptedException {
        final GRPCServer server = new GRPCServer();
        server.start();
        server.blockUntilShutdown();
    }
}

3.5.服务端启动

通过执行GRPCServer的main方法,
就能启动服务了,
启动成功打印日志:

Server started, listening on 50051
4.创建服务端工程

创建Maven工程,grpc-client。

4.1.修改pom.xml

操作步骤和上面服务端相同。

4.2.拷贝生成的代码

操作步骤和上面服务端相同。
由于客户端和服务端都依赖了生成的代码,
以及依赖相同的jar包,
可以提取到common公共工程里面,
这样方便其他工程依赖和后续修改。

4.3.创建客户端调用类

创建一个简单的客户端,
用于测试greeting服务,
创建GRPCClient.java:

package com.asiainfo.yuwen.grpc.client;

import java.util.concurrent.TimeUnit;

import com.asiainfo.yuwen.grpc.helloworld.GreeterGrpc;
import com.asiainfo.yuwen.grpc.helloworld.HelloWorldProto.HelloReply;
import com.asiainfo.yuwen.grpc.helloworld.HelloWorldProto.HelloRequest;

import io.grpc.Channel;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;

/**
 * 一个简单的客户端,测试greeting服务
 */
public class GRPCClient {

    private final GreeterGrpc.GreeterBlockingStub greeterBlocStub;

    /**
     * 构造使用现有通道访问服务端的客户端
     */
    public GRPCClient(Channel channel) {
        // 'channel'在这里是Channel,而不是ManagedChannel,所有它负责关闭

        // 向代码传递通道可以使代码更容易测试,也可以更容易地重用通道。
        // 同时这里创建的是同步(阻塞)RPC服务。
        greeterBlocStub = GreeterGrpc.newBlockingStub(channel);
    }

    /** 向服务端发送请求 */
    public void greet(String name) {
        System.out.println("Will try to greet " + name + " ...");
        HelloRequest request = HelloRequest.newBuilder().setName(name).build();
        HelloReply response;
        try {
            respOnse= greeterBlocStub.sayHello(request);
        } catch (StatusRuntimeException e) {
            System.out.println("WARNING, RPC failed: Status=" + e.getStatus());
            return;
        }
        System.out.println("Greeting: " + response.getMessage());
    }

    /**
     * 客户端启动入口,可以支持填写2个参数,否则使用默认值。 第1个参数是用户名。 第2个参数是目标服务器,格式IP:Port。
     */
    public static void main(String[] args) throws Exception {
        String user = "world";
        // 访问本机在50051端口上运行的服务
        String target = "localhost:50051";
        // 命令行用法帮助,允许将用户名和目标服务器作为命令行参数传入。
        if (args.length > 0) {
            if ("--help".equals(args[0])) {
                System.err.println("Usage: [name [target]]");
                System.err.println("");
                System.err.println("  name    The name you wish to be greeted by. Defaults to " + user);
                System.err.println("  target  The server to connect to. Defaults to " + target);
                System.exit(1);
            }
            user = args[0];
        }
        if (args.length > 1) {
            target = args[1];
        }

        // 创建到服务器的通信通道,通道是线程安全的和可重用的。
        // 通常在应用程序开始时创建通道,并重用直到应用程序关闭。
        ManagedChannel channel = ManagedChannelBuilder.forTarget(target).usePlaintext().build();
        try {
            GRPCClient client = new GRPCClient(channel);
            client.greet(user);
        } finally {
            // ManagedChannel使用像线程和TCP连接这样的资源。
            // 为了防止泄漏这些资源,通道应该在不再使用时关闭。
            channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
        }
    }
}

4.4.客户端启动

通过执行GRPCClient的main方法,
就能启动客户端了,
通过gRPC调用服务端成功后打印日志:

Will try to greet world ...
Greeting: Hello world
5.参考文档

GRPC的JAVA使用介绍
Grpc系列一 第一个hello world 例子


推荐阅读
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 开发笔记:spring boot项目打成war包部署到服务器的步骤与注意事项
    本文介绍了将spring boot项目打成war包并部署到服务器的步骤与注意事项。通过本文的学习,读者可以了解到如何将spring boot项目打包成war包,并成功地部署到服务器上。 ... [详细]
  • 本文介绍了在sqoop1.4.*版本中,如何实现自定义分隔符的方法及步骤。通过修改sqoop生成的java文件,并重新编译,可以满足实际开发中对分隔符的需求。具体步骤包括修改java文件中的一行代码,重新编译所需的hadoop包等。详细步骤和编译方法在本文中都有详细说明。 ... [详细]
  • 使用freemaker生成Java代码的步骤及示例代码
    本文介绍了使用freemaker这个jar包生成Java代码的步骤,通过提前编辑好的模板,可以避免写重复代码。首先需要在springboot的pom.xml文件中加入freemaker的依赖包。然后编写模板,定义要生成的Java类的属性和方法。最后编写生成代码的类,通过加载模板文件和数据模型,生成Java代码文件。本文提供了示例代码,并展示了文件目录结构。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • Spring框架《一》简介
    Spring框架《一》1.Spring概述1.1简介1.2Spring模板二、IOC容器和Bean1.IOC和DI简介2.三种通过类型获取bean3.给bean的属性赋值3.1依赖 ... [详细]
  • 本文介绍了解决java开源项目apache commons email简单使用报错的方法,包括使用正确的JAR包和正确的代码配置,以及相关参数的设置。详细介绍了如何使用apache commons email发送邮件。 ... [详细]
  • Hadoop2.6.0 + 云centos +伪分布式只谈部署
    3.0.3玩不好,现将2.6.0tar.gz上传到usr,chmod-Rhadoop:hadophadoop-2.6.0,rm掉3.0.32.在etcp ... [详细]
author-avatar
朱劭文_850
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有