首页 > 其他分享 >《RPC实战与核心原理》学习笔记Day5

《RPC实战与核心原理》学习笔记Day5

时间:2023-01-22 21:33:57浏览次数:45  
标签:java protobuf grpc Day5 System 笔记 server RPC io

06 | RPC实战:剖析gRPC源码,动手实现一个完整的RPC

我们通过动态代理技术,屏蔽RPC调用的细节,从而让使用者能够面向接口编程。

什么是gRPC?

gRPC是由Google开发并且开源的一款高性能、跨语言的RPC框架,当前支持C、Java和Go语言,当前Java版本最新Release版是1.51.3。

什么是protobuf?

protocol buffers是一种语言无关、平台无关、可扩展的序列化结构数据方法,可用于通信协议、数据存储等。
我们可以定义数据结构,然后使用特殊生成的源代码在各种数据流中使用各种语言进行编写和读取数据结构,也可以更新数据结构。

protobuf的三大特点:

  1. 语言无关,平台无关
  2. 灵活、高效
  3. 扩展性、兼容性好

下面我们来看一下如何使用gRPC。

首先我们需要安装protobuf,如果你使用Mac电脑,那么可以运行下面的命令来安装protobuf。

brew install protobuf

执行成功后,可以运行下面的命令来查看相关版本信息。

protoc --version

libprotoc 3.21.9

然后我们来创建下面的proto文件hello.proto。

syntax = "proto3";

option java_generic_services = true;
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

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

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

我们可以使用下面的命令来自动生成Java代码文件。

protoc ./hello.proto --java_out=./

命令执行完成后,会在当前目录下,生成代码文件,对应的目录结构如下。

tree .
.
├── hello.proto
└── io
    └── grpc
        └── examples
            └── helloworld
                ├── Greeter.java
                ├── Hello.java
                ├── HelloReply.java
                ├── HelloReplyOrBuilder.java
                ├── HelloRequest.java
                └── HelloRequestOrBuilder.java

上面就完成了proto文件转换的过程。

接下来,我们看怎么在Java工程中完整的使用gRPC。

我们创建一个空的Maven工程,在pom.xml中引用必要的依赖以及protobuf 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>sample.grpc</groupId>
	<artifactId>grpc-sample</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<grpc.version>1.52.1</grpc.version>
		<protobuf.version>3.21.9</protobuf.version>
	</properties>


	<dependencies>
		<dependency>
			<groupId>io.grpc</groupId>
			<artifactId>grpc-netty-shaded</artifactId>
			<version>1.29.0</version>
		</dependency>
		<dependency>
			<groupId>io.grpc</groupId>
			<artifactId>grpc-protobuf</artifactId>
			<version>1.29.0</version>
		</dependency>
		<dependency>
			<groupId>io.grpc</groupId>
			<artifactId>grpc-stub</artifactId>
			<version>1.29.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat</groupId>
			<artifactId>annotations-api</artifactId>
			<version>6.0.53</version>
			<scope>provided</scope>
		</dependency>

	</dependencies>

	<build>
		<extensions>
			<extension>
				<groupId>kr.motd.maven</groupId>
				<artifactId>os-maven-plugin</artifactId>
				<version>1.6.2</version>
			</extension>
		</extensions>
		<plugins>
			<plugin>
				<groupId>org.xolstice.maven.plugins</groupId>
				<artifactId>protobuf-maven-plugin</artifactId>
				<version>0.6.1</version>
				<configuration>
					<protocArtifact>com.google.protobuf:protoc:3.11.0:exe:${os.detected.classifier}</protocArtifact>
					<pluginId>grpc-java</pluginId>
					<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.29.0:exe:${os.detected.classifier}</pluginArtifact>
				</configuration>
				<executions>
					<execution>
						<goals>
							<goal>compile</goal>
							<goal>compile-custom</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

然后将上面的hello.proto文件复制到src/main/proto目录下面创建hello.proto目录下, 这个目录是固定的。

pom.xml文件准备好以后,我们来运行下面的工程编译命令。

maven compile

编译结束后,会在target/generated-sources目录下维护自动生成的代码,目录结构如下。

tree target/generated-sources
target/generated-sources
└── protobuf
    ├── grpc-java
    │   └── io
    │       └── grpc
    │           └── examples
    │               └── helloworld
    │                   └── GreeterGrpc.java
    └── java
        └── io
            └── grpc
                └── examples
                    └── helloworld
                        ├── Greeter.java
                        ├── Hello.java
                        ├── HelloReply.java
                        ├── HelloReplyOrBuilder.java
                        ├── HelloRequest.java
                        └── HelloRequestOrBuilder.java

11 directories, 7 files

接下来,我们来编写服务器端,代码如下。

package io.grpc.examples.helloworld;

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

import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;

public class HelloWorldServer {


    private Server server;

    private void start() throws IOException {
        /* The port on which the server should run */
        int port = 50051;
        server = ServerBuilder.forPort(port)
                .addService(new GreeterImpl())
                .build()
                .start();
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                // Use stderr here since the logger may have been reset by its JVM shutdown hook.
                System.err.println("*** shutting down gRPC server since JVM is shutting down");
                try {
                    HelloWorldServer.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);
        }
    }

    /**
     * Await termination on the main thread since the grpc library uses daemon threads.
     */
    private void blockUntilShutdown() throws InterruptedException {
        if (server != null) {
            server.awaitTermination();
        }
    }

    /**
     * Main launches the server from the command line.
     */
    public static void main(String[] args) throws IOException, InterruptedException {
        final HelloWorldServer server = new HelloWorldServer();
        server.start();
        server.blockUntilShutdown();
    }

    static class GreeterImpl extends GreeterGrpc.GreeterImplBase {

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

编写完成后,直接运行,这样会启动一个Server,端口是50051。

最后,我们来编写客户端,代码如下。

package io.grpc.examples.helloworld;

import java.util.concurrent.TimeUnit;

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

public class HelloWorldClient {

    private final GreeterGrpc.GreeterBlockingStub blockingStub;

    /** Construct client for accessing HelloWorld server using the existing channel. */
    public HelloWorldClient(Channel channel) {
        blockingStub = GreeterGrpc.newBlockingStub(channel);
    }

    /** Say hello to server. */
    public void greet(String name) {
        HelloRequest request = HelloRequest.newBuilder().setName(name).build();
        HelloReply response;
        try {
            response = blockingStub.sayHello(request);
        } catch (StatusRuntimeException e) {
            return;
        }
        System.out.println("Greeting: " + response.getMessage());
    }

    public static void main(String[] args) throws Exception {
        String user = "hahahahaha";
        // Access a service running on the local machine on port 50051
        String target = "localhost:50051";
        // Allow passing in the user and target strings as command line arguments
        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 {
            HelloWorldClient client = new HelloWorldClient(channel);
            client.greet(user);
        } finally {
            channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
        }
    }
}

当我们多次运行客户端程序后,我们可以在服务器端的控制台上,看到如下输出。

=====server=====
server: Hello hahahahah
=====server=====
server: Hello hahahahah
=====server=====
server: Hello hahahahah

这说明,客户端和服务器端在gRPC框架下面通信正常。

标签:java,protobuf,grpc,Day5,System,笔记,server,RPC,io
From: https://www.cnblogs.com/wing011203/p/17064686.html

相关文章

  • AC 自动机学习笔记
    前置知识:KMP,trie。一.自动机这里的自动机都指有限状态自动机(DFA)。一个DFA可以理解为一张有向图,由有限的状态(点),字母表,转移函数(边),开始状态与终止状态(起点,终点)组成。AC......
  • 学习笔记——SpringMVC拦截器的两种装配方式;SpringMVC拦截器工作原理;SpringMVC中的异
    2023-01-22 一、SpringMVC拦截器的两种装配方式1、全局装配(放置在springmvc.xml中)<!--装配拦截器--><!--全局装配--><mvc:interceptors><ref......
  • 数据结构笔记(一)
    程序=数据结构+算法数据结构(C语言版)(第2版)https://weread.qq.com/web/reader/b57320b071db572cb578fb5数据结构与算法基础(青岛大学-王卓)https://www.bilibili.com/video......
  • Elasticsearch 核心技术与实战 学习笔记
    分片的设定对于生产环境中分片的设定,需要提前做好容量规划分片数设置过小导致后续无法增加节点实现水品扩展单个分片的数据量太大,导致数据重新分配耗时分片数设......
  • 数论笔记
    ·质数素数定理:设\(x\geq1\),以\(\pi(x)\)表示不超过\(x\)的素数的个数。当\(x\rightarrow\infty\)时,\(\pi(x)\to\dfrac{x}{\ln(x)}\)质数筛法1.埃式......
  • 读函数式编程思维笔记03_权责让渡
    1. 观点1.1. 抽象隐藏了繁杂的细节,只是有时候会连同重要的考虑因素一起隐藏掉1.2. 理解掌握的抽象层次永远要比日常使用的抽象层次更深一层1.3. 交出控制权的观点:......
  • JavaScript学习笔记—数组
    1.描述数组也是一种复合数据类型,在数组中可以存储多个不同类型的数据数组中存储的是有序的数据,数组中的每个数据都有一个唯一的索引,可以通过索引来操作获取数据数组中......
  • ABB 800XA学习笔记35:AC 800M硬件结构16
    这一片学习笔记我在新浪博客发表过,地址是ABB800XA学习笔记35:A800M硬件16_来自金沙江的小鱼_新浪博客(sina.com.cn)在这里我再记录一遍,以免丢失继续学习,AC800M硬件快学习......
  • ABB 800XA学习笔记34: AC 800M硬件结构15
    这一篇学习笔记我在新浪博客记录过,地址是ABB800XA学习笔记34:AC800M硬件15_来自金沙江的小鱼_新浪博客(sina.com.cn)在这里我也记录一遍,以免丢失继续学习,AC800M硬件也快......
  • 新概念2册L9学习笔记
    L9Acoldwelcome本章词汇和语法介词+时间welcome/crowd/shoutwelcomen.v.欢迎welcomesb/sthTheywarmlywelcomeus;Iwelcomeanysuggestitions......