首页 > 其他分享 >基于springboot的grpc服务端demo

基于springboot的grpc服务端demo

时间:2024-08-28 17:07:11浏览次数:11  
标签:springboot grpc demo envoy header type com name

1. Java


maven配置

点击查看代码
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>grpc-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>grpc-demo</name>
    <description>grpc-demo</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>


        <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>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>1.29.0</version>
        </dependency>
        <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>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>annotations-api</artifactId>
            <version>6.0.53</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-server-spring-boot-starter</artifactId>
            <version>3.1.0.RELEASE</version>
        </dependency>

    </dependencies>



    <build>
<!--        os-maven-plugin:此插件可以检测当前系统信息-->
<!--        ${os.detected.classifier}:这个变量获取操作系统的版本,例如osx-x86_64-->
        <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>
                    <!-- 设置 protoc 的版本 -->
                    <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>
                    <!-- proto文件目录 -->
                    <protoSourceRoot>${project.basedir}/src/main/resources</protoSourceRoot>
                    <!-- 设置输出目录 -->
                    <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
                    <clearOutputDirectory>false</clearOutputDirectory>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <!--编译消息对象-->
                            <goal>compile</goal>
                            <!--依赖消息对象,生成接口服务-->
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>

</project>

application.yml

grpc:
  server:
    port: 18081

proto文件

我的放在了resource目录下,是在maven配置中设置的

syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.example.grpcdemo.grpc.user.auto";
option java_outer_classname = "UserProto";

service UserService {
  rpc saveUser (SaveUserRequest) returns (SaveUserReply);
  rpc queryUser (QueryUserRequest) returns (QueryUserReply);
}

message SaveUserRequest {
  string name = 1;
  string age = 2;
  string sex = 3;
}

message SaveUserReply {
  string status = 1;
}

message QueryUserRequest{
  string name = 1;
}

message QueryUserReply{
  string name = 1;
  string age = 2;
  string sex = 3;
}

打包之后auto文件夹下会自动生成编译后的文件



编辑你的服务类UserService

package com.example.grpcdemo.grpc.user;

import com.example.grpcdemo.grpc.user.auto.QueryUserReply;
import com.example.grpcdemo.grpc.user.auto.QueryUserRequest;
import com.example.grpcdemo.grpc.user.auto.SaveUserReply;
import com.example.grpcdemo.grpc.user.auto.SaveUserRequest;
import com.example.grpcdemo.grpc.user.auto.UserServiceGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;


@GrpcService
public class UserService extends UserServiceGrpc.UserServiceImplBase {
    @Override
    public void saveUser(SaveUserRequest request, StreamObserver<SaveUserReply> responseObserver) {
        System.out.println(request.toBuilder().build());
        SaveUserReply success = SaveUserReply.newBuilder()
                .setStatus("success")
                .build();
        responseObserver.onNext(success);
        responseObserver.onCompleted();
    }

    @Override
    public void queryUser(QueryUserRequest request, StreamObserver<QueryUserReply> responseObserver) {
        System.out.println(request.getName());
        QueryUserReply reply = QueryUserReply.newBuilder()
                .setAge("12")
                .setName("小王")
                .build();
        responseObserver.onNext(reply);
        responseObserver.onCompleted();
    }


}

使用apiPost调用接口


附带一些常用的格式

    @Override
    public void query1(Query1Request request, StreamObserver<Query1Response> responseObserver) {

        Query1Response response = Query1Response.newBuilder()
                .addUserArr(UserObj.newBuilder().setName("小王").setAge(20).build())
                .addUserArr(UserObj.newBuilder().setName("小李").setAge(21).build())
                .addUserArr(UserObj.newBuilder().setName("小赵").setAge(22))

                .addStringList("string1")
                .addStringList("string2")

                .putAMap("key1", "value1")
                .putAMap("key2", "value2")
                .build();

        responseObserver.onNext(response);
        responseObserver.onCompleted();
    }

接口返回:

2. 代理

浏览器目前不支持发送http2.0的请求,所以前端使用grpc-web封装请求,经过代理请求grpc服务端。nginx代理和envoy代理都可以。

     2.1 Nginx


    server {
        # TODO 1/2 配置监听的浏览器端口号
        listen       19090;
        http2 on;
        server_name  localhost;

        location / {
            # 重点!!需要将Content-Type更改为 application/grpc
            # grpc-web过来的是application/grpc-web+proto || application/grpc-web+text (取决于生成js代码时grpc-web_out 的mode选项,本文用grpcweb 则为application/grpc-web+proto)
            grpc_set_header Content-Type application/grpc;
            # grpc_set_header TE trailers;

            # TODO 2/2 配置要转到的grpc服务和端口号
            grpc_pass grpc://192.168.3.100:19094;
            # grpc_ssl_verify off; # 关闭对grpc服务器的ssl证书验证
            
            # 因浏览器有跨域限制,这里直接在nginx支持跨域
            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Transfer-Encoding,Custom-Header-1,X-Accept-Content-Transfer-Encoding,X-Accept-Response-Streaming,X-User-Agent,X-Grpc-Web';
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;
            }
            if ($request_method = 'POST') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Transfer-Encoding,Custom-Header-1,X-Accept-Content-Transfer-Encoding,X-Accept-Response-Streaming,X-User-Agent,X-Grpc-Web';
                add_header 'Access-Control-Expose-Headers' 'Content-Transfer-Encoding, grpc-message,grpc-status';
                add_header 'Content-Type' 'text/plain charset=UTF-8';
            }

        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }


     2.2 Envoy


envoy构建困难,好像目前只支持在docker部署
envoy中文网:https://icloudnative.io/envoy-handbook/docs/gettingstarted/setup/

envoy安装
# 获取镜像
docker pull envoyproxy/envoy

# 启动 Envoy 容器时,可以用本地的 envoy.yaml 覆盖镜像中的 envoy.yaml
docker run -it -d \
--name envoy \
-p 19090:19090 \
-v /home/yk/envoyConfig/envoy.yaml:/etc/envoy/envoy.yaml\
 envoyproxy/envoy

# 启动envoy
envoy -c envoy.yaml
envoy.yml
admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address: { address: 0.0.0.0, port_value: 19090 }
      filter_chains:
        - filters:
          - name: envoy.filters.network.http_connection_manager
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
              codec_type: auto
              stat_prefix: ingress_http
              route_config:
                name: local_route
                virtual_hosts:
                  - name: local_service
                    domains: ["*"]
                    routes:
                      - match: { prefix: "/" }
                        route:
                          cluster: echo_service
                          timeout: 0s
                          max_stream_duration:
                            grpc_timeout_header_max: 0s
                    cors:
                      allow_origin_string_match:
                        - prefix: "*"
                      allow_methods: GET, PUT, DELETE, POST, OPTIONS
                      allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
                      max_age: "1728000"
                      expose_headers: custom-header-1,grpc-status,grpc-message
              http_filters:
                - name: envoy.filters.http.grpc_web
                  typed_config:
                    "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
                - name: envoy.filters.http.cors
                  typed_config:
                    "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
                - name: envoy.filters.http.router
                  typed_config:
                    "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
    - name: echo_service
      connect_timeout: 0.25s
      type: logical_dns
      # HTTP/2 support
      typed_extension_protocol_options:
        envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
          "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
          explicit_http_config:
            http2_protocol_options: {}
      lb_policy: round_robin
      load_assignment:
        cluster_name: cluster_0
        endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: 192.168.3.100
                    port_value: 19094

标签:springboot,grpc,demo,envoy,header,type,com,name
From: https://www.cnblogs.com/krcc/p/18385123

相关文章

  • 03. SpringBoot 项目创建
    接下来我们将要完成一个基础的Springboot项目的创建,并且将项目上传到Gitee1.查看官网,选择版本学习任何一门技术,一定要学会从官网了解一手信息,无论是哪个博主的博客都是有时效性的,我们要掌握这样的习惯,看懂看不懂另说,起码知道从哪里去找。spring官网地址:https://sp......
  • springboot基于vue的汽车租赁系统
    目录摘要 1Abstract 1目录 21绪论 41.1研究背景与意义 41.2国内外研究现状 41.3研究内容 51.4论文结构 51.5本章小结 52理论基础 62.1B/S模式 62.2IDEA开发环境 62.3MySQL数据库 62.4Java语言 72.5本章小结 73需求分析 83.1功能需求分......
  • springboot针对老年人的景区订票系统
    系统包含:源码+论文所用技术:SpringBoot+Vue+SSM+Mybatis+Mysql免费提供给大家参考或者学习,获取资料请私聊我目录目录 III1绪论 11.1研究背景 11.2目的和意义 11.3论文结构安排 22相关技术 32.1B/S结构介绍 32.2MySQL数据库介绍 32.3SpringBoot框......
  • springboot大学生科创项目在线管理系统的设计与实现
    系统包含:源码+论文所用技术:SpringBoot+Vue+SSM+Mybatis+Mysql免费提供给大家参考或者学习,获取资料请私聊我目录目录 III第1章绪论 11.1选题动因 11.2目的和意义 11.3论文结构安排 2第2章开发环境与技术 32.1MYSQL数据库 32.2Tomcat介绍 32.3vue技......
  • SpringBoot配置动态数据源 原理+实战
    若没空探究原理可直接跳转到“实现方式:注解+切面”目录数据源切换方法Spring对数据源的管理类似于策略模式,不懂策略模式也没关系,其实就是有一个全局的键值对,类型是Map<String,DataSource>。当JDBC操作数据库之时,会根据不同的key值选择不同的数据源。而这个key值可以放到方法的......
  • SpringBoot配置多个kafka配置
    引入依赖<dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId><version>2.7.14</version></dependency>yml配置有几个就配置几个......
  • 【SQL练习】demo1
    为了适应技术发展的需求,SQL标准于2016年增加了以下JSON功能:JSON对象的存储与检索。将JSON对象表示成SQL数据。将SQL数据表示成JSON对象。如今,主流关系型数据库都增加了原生JSON数据类型和相关函数的支持,使得我们可以将SQL的强大功能与JSON文档存储的灵......
  • Springboot计算机毕业设计汽车销售管理系统3ytu1
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表用户,员工,汽车分类,汽车品牌,汽车颜色,汽车信息,汽车预订,汽车入库,数据统计,反馈信息开题报告内容一、毕业设计(论文)题目的来源、理论或实际应用意义1.1题目......
  • 基于java的SpringBoot框架卫生健康系统
    博主介绍:java高级开发,从事互联网行业六年,熟悉各种主流语言,精通java、python、爬虫、web开发,已经做了六年的程序开发,开发过上千套大学生实战程序,可以定制、也可成品项目,博客中有上百套程序可供参考,欢迎共同交流学习。......
  • 使用idea快速创建springbootWeb项目(springboot+springWeb+mybatis-Plus)
    idea快速创建springbootWeb项目详细步骤如下1)创建项目2)选择springboot版本3)添加web依赖4)添加Thymeleaf5)添加lombok依赖然后点击create进入下一步双击pom.xml文件6)添加mybatis-plus依赖        这里使用的springboot版本比较新,mybatis-plus-boot-star......