百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Spring Boot集成grpc快速入门demo

ccwgpt 2024-10-13 01:32 78 浏览 0 评论

1.什么是GRPC?

gRPC 是一个高性能、开源、通用的RPC框架,由Google推出,基于HTTP2协议标准设计开发,默认采用Protocol Buffers数据序列化协议,支持多种开发语言。gRPC提供了一种简单的方法来精确的定义服务,并且为客户端和服务端自动生成可靠的功能库。 在gRPC客户端可以直接调用不同服务器上的远程程序,使用姿势看起来就像调用本地程序一样,很容易去构建分布式应用和服务。和很多RPC系统一样,服务端负责实现定义好的接口并处理客户端的请求,客户端根据接口描述直接调用需要的服务。客户端和服务端可以分别使用gRPC支持的不同语言实现。

主要特性

  • 强大的IDLgRPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议(类似于XML、JSON、hessian)。ProtoBuf能够将数据进行序列化,并广泛应用在数据存储、通信协议等方面。
  • 多语言支持gRPC支持多种语言,并能够基于语言自动生成客户端和服务端功能库。目前已提供了C版本grpc、Java版本grpc-java 和 Go版本grpc-go,其它语言的版本正在积极开发中,其中,grpc支持C、C++、Node.js、Python、Ruby、Objective-C、PHP和C#等语言,grpc-java已经支持Android开发。
  • HTTP2gRPC基于HTTP2标准设计,所以相对于其他RPC框架,gRPC带来了更多强大功能,如双向流、头部压缩、多复用请求等。这些功能给移动设备带来重大益处,如节省带宽、降低TCP链接次数、节省CPU使用和延长电池寿命等。同时,gRPC还能够提高了云端服务和Web应用的性能。gRPC既能够在客户端应用,也能够在服务器端应用,从而以透明的方式实现客户端和服务器端的通信和简化通信系统的构建。

2.代码工程

我们建议将您的项目分为2至3个不同的模块。

  1. grpc-api 项目 包含原始 protobuf 文件并生成 java model 和 service 类。 你可能会在不同的项目中会共享这个部分。
  2. grpc-Server 项目 包含项目的业务实现,并使用上面的 Interface 项目作为依赖项。
  3. grpc-Client 项目(可选,可能很多) 任何使用预生成的 stub 来访问服务器的客户端项目。

实验目的

定义了一个Hello Service,客户端发送包含字符串名字的请求,服务端返回Hello消息。

grpc-api

pom.xml

<?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">
    <parent>
        <artifactId>grpc</artifactId>
        <groupId>com.et</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>grpc-api</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <protobuf.version>3.23.4</protobuf.version>
        <protobuf-plugin.version>0.6.1</protobuf-plugin.version>
        <grpc.version>1.58.0</grpc.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>${grpc.version}</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>${grpc.version}</version>
        </dependency>
        <dependency>
            <!-- Java 9+ compatibility - Do NOT update to 2.0.0 -->
            <groupId>jakarta.annotation</groupId>
            <artifactId>jakarta.annotation-api</artifactId>
            <version>1.3.5</version>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.7.0</version>
            </extension>
        </extensions>

        <plugins>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>${protobuf-plugin.version}</version>
                <configuration>
                    <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>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

proto

将您的 protobuf 定义/.proto文件放入src/main/proto。 有关编写 protobuf 文件的信息,请参阅官方的 protobuf 文档。 您的 .proto 文件跟如下的示例类似:

syntax = "proto3";

package net.devh.boot.grpc.example;

option java_multiple_files = true;
option java_package = "com.et.grpc.api.protobuf.lib";
option java_outer_classname = "HelloWorldProto";

// The greeting service definition.
service MyService {
    // 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;
}

生成文件,源码在target/generated-sources/protobuf

mvn protobuf:compile
mvn protobuf:compile-custom

最后打包给server和client引用

grpc-server

protoc-gen-grpc-java 插件为你的每个 grpc 服务生成一个类。 例如:MyServiceGrpcMyService 是 proto 文件中的 grpc 服务名称。 这个类 包含您需要扩展的客户端 stub 和服务端的 ImplicBase。 在这之后,你还有四个步骤:

  1. 请确保您的 MyServiceImp 实现了 MyServiceGrpc.MyServiceImpBase
  2. @GrpcService 注解添加到您的 MyServiceImp 类上
  3. 请确保 MyServiceImplic 已添加到您的应用程序上下文中。通过在您的 @Configuration 类中创建 @Bean或者将其放置在 spring 的自动检测到路径中(例如在您Main类的相同或子包中)
  4. 实现 grpc 服务方法。

pom.xml

<?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">
    <parent>
        <artifactId>grpc</artifactId>
        <groupId>com.et</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>grpc-server</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-server-spring-boot-starter</artifactId>
            <version>${grpc.version}</version>
        </dependency>
        <dependency>
            <groupId>com.et</groupId>
            <artifactId>grpc-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

service

/*
 * Copyright (c) 2016-2023 The gRPC-Spring Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.et.grpc.server;

import com.et.grpc.api.protobuf.lib.HelloReply;
import com.et.grpc.api.protobuf.lib.HelloRequest;
import com.et.grpc.api.protobuf.lib.MyServiceGrpc;
import io.grpc.stub.StreamObserver;

import net.devh.boot.grpc.server.service.GrpcService;

/**
 * @author Michael (yidongnan@gmail.com)
 * @since 2016/11/8
 */

@GrpcService
public class GrpcServerService extends MyServiceGrpc.MyServiceImplBase {

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

}

application.yaml

spring:
  application:
    name: local-grpc-server
grpc:
  server:
    port: 9898

grpc-client

以下列表包含您可能在客户端使用到的的所有功能。 如果您不想使用任何高级功能,那么前两个元素可能都是您需要使用的。

  • @GrpcClient: 在需要注入的客户端的字段或者 setter 方法上这个注解。 支持 Channel和各种类型的 Stub。 请不要将 @GrpcClient@Autowireed@Inject 一起使用。 目前,它不支持构造函数和 @Bean 方法参数。 这种情况请查看后面 @GrpcClientBean 的使用文档。 注意: 同一应用程序提供的服务只能在 ` ApplicationStartedEvent 之后访问/调用。 连接到外部服务的 Stubs 可以提前使用;从 @PostConstruct / 初始化Bean#afterPropertiesSet()` 开始。
  • @GrpcClientBean: 注解会把使用 @GrpcClient 注解的类型注册到 Spring Context 中,方便 @Autowired@Qualifier 的使用。 这个注解可以重复添加到您的 @Configuration 类中。
  • Channel: Channel 是单个地址的连接池。 目标服务器可能是多个 gRPC 服务。 该地址将使用 NameResolver 做解析,最终它可能会指向一批固定数量或动态数量的服务端。
  • ManagedChannel: ManagedChannel 是 Channel 的一种特殊变体,因为它允许对连接池进行管理操作,例如将其关闭。
  • NameResolverNameResolver.Factory: 一个用于将地址解析为SocketAddress 列表的类 ,当与先前列出的服务端连表连接失败或通道空闲时,地址将会重新做解析。 参阅 Configuration -> Choosing the Target。
  • ClientInterceptor: 在每个 Channel 处理之前拦截它们。 可以用于日志、监测、元数据处理和请求/响应的重写。 grpc-spring-boot-starter 将自动接收所有带有 @GrpcGlobalClientInterceptor 注解以及手动注册在GlobalClientInterceptorRegistry 上的客户拦截器。 参阅 Configuration -> ClientInterceptor。
  • CallCredentials: 管理身份验证的组件。 它可以用于存储凭据和会话令牌。 它还可以用来身份验证,并且使用返回的令牌(例如 OAuth) 来授权实际请求。 除此之外,如果令牌过期并且重新发送请求,它可以续签令牌。 如果您的应用程序上下文中只存在一个 CallCredentials bean,那么 spring 将会自动将其附加到Stub Channel )。 CallCredentialsHelper工具类可以帮助您创建常用的 CallCredentials 类型和相关的StubTransformer
  • StubFactory: 一个用于从 Channel 创建特定 Stub 的工厂。 可以注册多个 StubFactory,以支持不同类型的 stub。 参阅 Configuration -> StubFactory。
  • StubTransformer: 所有客户端的 Stub 的注入之前应用的转换器。 参阅 Configuration -> StubTransformer。

pom.xml

/*
 * Copyright (c) 2016-2023 The gRPC-Spring Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.et.grpc.client;

import com.et.grpc.api.protobuf.lib.HelloReply;
import com.et.grpc.api.protobuf.lib.HelloRequest;
import com.et.grpc.api.protobuf.lib.MyServiceGrpc;
import org.springframework.stereotype.Service;

import io.grpc.StatusRuntimeException;
import net.devh.boot.grpc.client.inject.GrpcClient;


/**
 * @author Michael (yidongnan@gmail.com)
 * @since 2016/11/8
 */
@Service
public class GrpcClientService {

    @GrpcClient("local-grpc-server")
    // @GrpcClient("cloud-grpc-server")
    private MyServiceGrpc.MyServiceBlockingStub myServiceStub;

    public String sendMessage(final String name) {
        try {
            final HelloReply response = this.myServiceStub.sayHello(HelloRequest.newBuilder().setName(name).build());
            return response.getMessage();
        } catch (final StatusRuntimeException e) {
            return "FAILED with " + e.getStatus().getCode().name();
        }
    }

}

controller

/*
 * Copyright (c) 2016-2023 The gRPC-Spring Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.et.grpc.client;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Michael (yidongnan@gmail.com)
 * @since 2016/12/4
 */
@RestController
public class GrpcClientController {

    @Autowired
    private GrpcClientService grpcClientService;

    @RequestMapping("/")
    public String printMessage(@RequestParam(defaultValue = "Michael") String name) {
        return grpcClientService.sendMessage(name);
    }

}

application.yaml

server:
  port: 8088
spring:
  application:
    name: local-grpc-client

grpc:
  client:
    local-grpc-server:
      address: 'static://127.0.0.1:9898'
      enableKeepAlive: true
      keepAliveWithoutCalls: true
      negotiationType: plaintext

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

  • https://github.com/Harries/springboot-demo

3.测试

  • 启动服务端
  • 启动客户端
  • 调用服务http://127.0.0.1:8088/

测试服务

您可以通过运行 gRPCurl 命令来测试您的应用程序是否正常运行:

grpcurl --plaintext localhost:9898 list
grpcurl --plaintext localhost:9898 list net.devh.boot.grpc.example.MyService
# Linux (Static content)
grpcurl --plaintext -d '{"name": "test"}' localhost:9898 net.devh.boot.grpc.example.MyService/sayHello
# Windows or Linux (dynamic content)
grpcurl --plaintext -d "{\"name\": \"test\"}" localhost:9898 net.devh.boot.grpc.example.MyService/sayHello

gRPCurl 的示例命令输出以及其他信息请参考此 文档

4.引用

  • https://yidongnan.github.io/grpc-spring-boot-starter/zh-CN/server/getting-started.html

相关推荐

如何使用PIL生成验证码?(pi验证教程)

web项目中遇到使用验证码的情况有很多,进行介绍下使用PIL生成验证码的方法。安装开始安装PIL的过程确实麻烦各种问题层出不绝,不过不断深入后就没有这方面的困扰了:windows安装:直接安装Pil...

Python必学!3步解锁asyncio异步编程 性能直接狂飙10倍!

还在用传统同步代码被IO阻塞卡到崩溃?别当“代码苦行僧”了!Python的asyncio模块堪称异步编程的“开挂神器”,处理高并发任务就像开了涡轮增压!不管是网络爬虫、API接口开发还是文件批量处理,...

Tornado6+APScheduler/Celery打造并发异步动态定时任务轮询服务

定时任务的典型落地场景在各行业中都很普遍,比如支付系统中,支付过程中因为网络或者其他因素导致出现掉单、卡单的情况,账单变成了“单边账”,这种情况对于支付用户来说,毫无疑问是灾难级别的体验,明明自己付了...

Python学习怎么入门?附真实学习方法

Python技术在企业中应用的越来越广泛,因此企业对于Python方面专业人才的需求也越来越大,那对于之前对Python没有任何了解和接触的人而言,想要从零开始学习并不是一件容易的事情,接下来小U就为...

PySpider框架的使用(pyspider 教程)

PysiderPysider是一个国人用Python编写的、带有强大的WebUI的网络爬虫系统,它支持多种数据库、任务监控、项目管理、结果查看、URL去重等强大的功能。安装pip3inst...

大学计算机专业 学习Python学习路线图(最新版)

这是我刚开始学习python时的一套学习路线,从入门到上手。(不敢说精通,哈哈~)希望对大家有帮助哈~大家需要高清得完整python学习路线可以【文末有获取方式】【文末有获取方式】一、Python入门...

阿里巴巴打造的400集Python视频合集免费学起来,学完万物皆可爬

第一阶段Python入门章节1:Python入门章节2:编程基本概念章节3:序列章节4:控制语句章节5:函数章节6:面向对象编程第二阶段Python深入与提高章节1:异常处理章节2:游戏开发-坦克大...

Nginx Gunicorn在服务器中分别起什么作用

大部分人在gunicorn前面部署一层nginx的时候也的确没有想过为什么,他们只是觉得这样显得他们比较专业,而且幻想着加了一层nginx反向代理之后性能会有提升,恕我直言,请你们带上脑子,一个单纯的...

Python培训怎么学?Python基础技术总结!值得一看

Python培训如今越来越被更多人所接受,相比自学参加Python培训的好处也是显而易见,但Python毕竟属于后端编程开发的主流语言,其知识机构还是比较庞大的,那Python培训怎么学?以及Pyth...

使用Tornado部署Flask项目(tornado async)

Tornado不仅仅是一个WEB框架,也可以是一个WEB服务器。在Tornado中我们可以使用wsgi模块下的WSGIContainer类运行其他WSGI应用如:Fask,Bottle,Djang...

Python Web框架哪个好用?(python3 web框架)

  问:PythonWeb框架哪个好用?  答:  1.Django  Django是Python世界中最出名、最成熟的Web框架。Django功能全面,各模块之间结合紧密,(不讲其他的)Djang...

Vue3.0+Tornado6.1发布订阅模式打造异步非阻塞实时=通信聊天系统

“表达欲”是人类成长史上的强大“源动力”,恩格斯早就直截了当地指出,处在蒙昧时代即低级阶段的人类,“以果实、坚果、根作为食物;音节清晰的语言的产生是这一时期的主要成就”。而在网络时代人们的表达欲往往更...

Python开源项目合集(第三方平台)(python第三方开发工具)

wechat-python-sdk-wechat-python-sdk微信公众平台Python开发包http://wechat-python-sdk.readthedocs.org/,非官方...

IT界10倍高效学习法!用这种方式,一年学完清华大学四年的课程

有没有在某一个瞬间,让你放弃学编程刚开始学python时,我找了几十本国内外的python编程书籍学习后,我还是似懂非懂,那些书里面到处都是抽象的概念,复杂的逻辑,这样的书,对于专业开发者来说,在平常...

如何将Python算法模型注册成Spark UDF函数实现全景模型部署

背景Background对于算法业务团队来说,将训练好的模型部署成服务的业务场景是非常常见的。通常会应用于三个场景:部署到流式程序里,比如风控需要通过流式处理来实时监控。部署到批任务中部署成API服...

取消回复欢迎 发表评论: