SpringBoot + Kotlin 中使用 GRPC 进行服务通信

news2024/9/29 1:23:55

示例项目见:kotlin-grpc

一、导入依赖:

import com.google.protobuf.gradle.*  
  
plugins {  
    id("org.springframework.boot") version "2.3.1.RELEASE"  
    id("io.spring.dependency-management") version "1.0.9.RELEASE"  
    id("org.asciidoctor.convert") version "1.5.9.2"  
    kotlin("jvm") version "1.6.0"  
    kotlin("plugin.spring") version "1.6.0"  
    id("com.google.protobuf") version "0.9.2"  
}  
  
repositories {  
    mavenCentral()  
}  
  
group = "com.whrss.kotlin-grpc"  
version = "0.0.1-SNAPSHOT"  
  
java.sourceCompatibility = JavaVersion.VERSION_1_8  
java.targetCompatibility = JavaVersion.VERSION_1_8  
  
sourceSets.main {  
    java.srcDirs("src/main/kotlin")  
}  
  
extra["spring-restdocs.version"] = "2.0.5.BUILD-SNAPSHOT"  
val snippetsDir by extra { file("build/generated-snippets") }  
  
dependencies {  
    implementation("com.google.protobuf:protobuf-java:3.22.2")  
    implementation("io.grpc:grpc-protobuf:1.53.0")  
    implementation("com.google.protobuf:protobuf-kotlin:3.22.2")  
    implementation("io.grpc:grpc-kotlin-stub:1.3.0")  
    implementation("io.grpc:grpc-netty:1.56.1")  
    implementation("io.grpc:grpc-all:1.56.1")  
}  
  
protobuf {  
    protoc {  
        artifact = "com.google.protobuf:protoc:3.19.4"  
    }  
    plugins {  
        id("grpc") {  
            artifact = "io.grpc:protoc-gen-grpc-java:1.40.1"  
        }  
        id("grpckt") {  
            artifact = "io.grpc:protoc-gen-grpc-kotlin:1.3.0:jdk8@jar"  
        }  
    }  
    // Enable Kotlin generation  
    generateProtoTasks {  
        all().forEach {  
            it.plugins {  
                id("grpc")  
                id("grpckt")  
            }  
        }    }}

二、设置Proto

proto 文件放在 src/mian/proto 目录下

syntax = "proto3";  
import "google/api/annotations.proto";  
option java_multiple_files = true;  
package hello_world.v1;  
service HelloWorldService{  
  rpc GetUserInfo (GetUserRequest) returns (GetUserReply) {  
    option (google.api.http) = {  
      get: "/api/v1/users"  
    };  
  }  
}  
message GetUserRequest{  
  // 用户showId  
  string userId = 1;  
}  
message GetUserReply{  
  // 用户showId  
  string userId = 1;  
}

执行 ./gradlew clean build

build成功则会在 build/generated/source/proto/main 下生成对应的 grpcgrpcktjava 文件
在程序中可以直接导包引入

三、Server端

写一个 service

import hello_world.v1.GetUserReply  
import hello_world.v1.GetUserRequest  
import hello_world.v1.HelloWorldServiceGrpcKt  
  
  
class Service : HelloWorldServiceGrpcKt.HelloWorldServiceCoroutineImplBase() {  
  
    override suspend fun getUserInfo(request: GetUserRequest) : GetUserReply {  
        println("getItemStatistics exec")  
        return GetUserReply.newBuilder()  
            .setUserId(request.userId)  
            .build()  
    }  
  
}

main 入口引入启动

import io.grpc.ServerBuilder  
  
  
fun main() {  
    helloServer()  
}  
fun helloServer() {  
    val helloService = Service()  
    val server = ServerBuilder  
        .forPort(15001)  
        .addService(helloService)  
        .build()  
  
    Runtime.getRuntime().addShutdownHook(Thread {  
        server.shutdown()  
        server.awaitTermination()  
    })  
  
    server.start()  
    println("server start")  
    server.awaitTermination()  
    println("server restart")  
}

四、Client 端

import hello_world.v1.GetUserRequest  
import hello_world.v1.HelloWorldServiceGrpc  
import io.grpc.ManagedChannelBuilder  
  
  
fun main() {  
    val channel = ManagedChannelBuilder.forAddress("localhost", 15001).usePlaintext()  
    val stub = HelloWorldServiceGrpc.newBlockingStub(channel.build())  
    val response = stub.getUserInfo(GetUserRequest.newBuilder().setUserId("0").build())  
    println(response)  
}

五、一些坑

io.grpc 和 com.google的一些依赖是有关联的,如果依赖版本之间有巨大差异,是会导致运行错误的。比如我之前使用到了一个google的一个特别老的依赖:com.google.code.google-collections:google-collect:snapshot-20080530,导致了我程序运行时提示:

Exception in thread "main" java.lang.NoSuchMethodError: 'void com.google.common.base.Preconditions.checkArgument(boolean, java.lang.String, char, java.lang.Object)'
	at io.grpc.Metadata$Key.validateName(Metadata.java:754)
	at io.grpc.Metadata$Key.<init>(Metadata.java:762)
	at io.grpc.Metadata$Key.<init>(Metadata.java:671)
	at io.grpc.Metadata$AsciiKey.<init>(Metadata.java:971)
	at io.grpc.Metadata$AsciiKey.<init>(Metadata.java:966)
	at io.grpc.Metadata$Key.of(Metadata.java:708)
	at io.grpc.Metadata$Key.of(Metadata.java:704)
	at io.grpc.internal.GrpcUtil.<clinit>(GrpcUtil.java:99)
	at io.grpc.netty.Utils.<clinit>(Utils.java:83)
	at io.grpc.netty.UdsNettyChannelProvider.isAvailable(UdsNettyChannelProvider.java:34)
	at io.grpc.ManagedChannelRegistry$ManagedChannelPriorityAccessor.isAvailable(ManagedChannelRegistry.java:211)
	at io.grpc.ManagedChannelRegistry$ManagedChannelPriorityAccessor.isAvailable(ManagedChannelRegistry.java:207)
	at io.grpc.ServiceProviders.loadAll(ServiceProviders.java:68)
	at io.grpc.ManagedChannelRegistry.getDefaultRegistry(ManagedChannelRegistry.java:101)
	at io.grpc.ManagedChannelProvider.provider(ManagedChannelProvider.java:43)
	at io.grpc.ManagedChannelBuilder.forAddress(ManagedChannelBuilder.java:39)
	at com.ck567.kotlingrpc.ClientKt.main(Client.kt:9)
	at com.ck567.kotlingrpc.ClientKt.main(Client.kt)

在google是发现不了具体的问题的,可以注意一下。

上面的依赖版本都是基于对应spring boot和 kotlin 版本的,如果你的版本不适配,可能也需要折腾一下,但问题应该不是很大。

如有问题,欢迎留言,能帮到的地方,我不会吝啬。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/737660.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面试官常问的一些初中级前端知识点

CSS 1. 介绍下 CSS 盒子模型 回答到以下两点就可以&#xff1a; 一个盒子由四个部分组成&#xff1a;content、padding、border、margin。两种盒子模型&#xff1a;W3C 标准盒子模型、IE 怪异盒子模型标准盒子模型 width / height 只是内容高度&#xff0c;不包含 padding 和…

平板ipad触控笔是哪几款?苹果笔性价比高的推荐

实际上&#xff0c;现在市场上许多产品都有各自的特色&#xff0c;一些注重产品外观&#xff0c;一些注重产品功能。就相当于ipad上所搭配的电容笔。所以&#xff0c;在购买电容笔的时候&#xff0c;必须对电容笔有一些认识。在选购前&#xff0c;必须先了解各种类型的电容笔&a…

7-8 程序员买包子

7-8 程序员买包子 分数 10 全屏浏览题目 切换布局 作者 陈越 单位 浙江大学 这是一条检测真正程序员的段子&#xff1a;假如你被家人要求下班顺路买十只包子&#xff0c;如果看到卖西瓜的&#xff0c;买一只。那么你会在什么情况下只买一只包子回家&#xff1f; 本题要求你考…

线程 线程池

线程和进程的区别? 进程是正在运行程序的实例&#xff0c;进程中包含了线程&#xff0c;每个线程执行不同的任务 不同的进程使用不同的内存空间&#xff0c;在当前进程下的所有线程可以共享内存空间 线程更轻量&#xff0c;线程上下文切换成本一般上要比进程上下文切换低 创…

博士后申请哪些老板不要选?

博士后申请是许多研究人员迈向学术界的重要阶段。在选择导师时&#xff0c;需要慎重考虑各方面因素。虽然我不能提及具体老板的名字&#xff0c;但我可以给你一些在博士后申请过程中需要谨慎选择的类型。以下是知识人网小编整理的一些可能不适合选择的老板类型&#xff1a; 1. …

Spring-AutowireFactoryBean

autowire autowire 即自动注入的意思&#xff0c;通过使用 autowire 特性&#xff0c;我们就不用再显示的配置 bean 之间的依赖了。把依赖的发现和注入都交给 Spring 去处理&#xff0c;省时又省力。autowire 几个可选项&#xff0c;比如 byName、byType 和 constructor 等。a…

刘铁猛C#教程学习笔记--初识C#程序

构成C#程序的基本元素 关键字&#xff1a;C#保留的用作特殊用途的标识符标识符&#xff1a;名字&#xff0c;如变量名字&#xff0c;类名字&#xff0c;命名空间名字等等&#xff1b; 标识符命名规则&#xff1a;只能以数字字母或者下划线开头&#xff0c;不能用关键字作为标识…

喜讯!云联壹云入选2023年北京市“专精特新”中小企业

6月25日&#xff0c;北京市经济和信息化局发布《关于对2023年第一季度北京市专精特新中小企业名单进行公告的通知》&#xff0c;北京云联壹云技术有限公司入选2023年北京市“专精特新”中小企业。 “专精特新”是国家为增强企业自主创新能力和核心竞争力&#xff0c;不断提高中…

HHDESK资源管理功能

为使客户体验更上一层楼&#xff0c;我们在最新的HHDESK版本中&#xff0c;新增了一个功能“资源管理”&#xff0c;其中不仅整合了原有的连接管理、网络代理功能&#xff0c;还增加了不少实用的新功能。 本篇便为您简单介绍一下。 1 本地服务 可以方便的调用本地资源。 比如…

基于STM32设计的酒精检测仪

一、需求分析 随着社会的发展和生活水平的提高&#xff0c;人们对于行车安全、家庭安全的要求越来越高&#xff0c;而酒驾等问题也日渐突出&#xff0c;为此&#xff0c;开发一款基于STM32的酒精检测仪&#xff0c;通过检测酒精浓度&#xff0c;实时显示结果并进行报警&#x…

openGauss学习笔记-05 openGauss gsql连接与使用方法

文章目录 openGauss学习笔记-05 openGauss gsql连接与使用方法5.1 以操作系统用户omm登录数据库主节点5.2 连接数据库5.3 数据库简单操作5.4 退出数据库 openGauss学习笔记-05 openGauss gsql连接与使用方法 openGauss提供了在命令行下运行的数据库连接工具gsql。此工具除了具…

【AI】在NVIDIA Jetson Orin Nano上使用tensorrtx部署yolov8

1、下载 1.1 权重文件下载 https://github.com/ultralytics/assets/releases本人下载的yolov8n.pt yolov8n-cls.pt:用于分类 yolov8n-pose.pt:用于姿势识别 yolov8n-seg.pt:用于对象分割 yolov8n-v8loader.pt:专用于人员检测器??? yolov8n.pt:用于对象检测 1.2 源码…

【Go|第7期】浅谈Lorca库中的Chromium命令行参数

日期&#xff1a;2023年7月9日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xff…

你想知道个人博客和企业博客具体区别吗?点进来看看吧

在互联网时代&#xff0c;越来越多人开始会去使用博客来记录生活中的点滴。博客已经成为了人们分享信息、表达观点的重要平台。无论是个人还是企业&#xff0c;都可以通过博客来传播自己的声音和观点。这篇文章looklook会聚焦于企业博客&#xff0c;从分析个人与企业博客的区别…

【峟思科普】水库监测点位布设原则

水库监测一般有常规监测、变形监测、应力监测和地质灾害监测等&#xff0c;其中变形监测是水库安全的重要保障&#xff0c;是通过安装在水库坝体或大坝周边的变形监测仪来测量坝体或坝基表面的变形情况&#xff0c;如位移、沉降、裂缝、倾斜等。下面给大家介绍下水库监测点位布…

Android复杂UI的性能优化实践 - PTQBookPageView 性能优化记录

作者&#xff1a;彭泰强 1 评价指标&优化成果 要做性能优化&#xff0c;首先得知道性能怎么度量、怎么表示。因为性能是一个很抽象的词&#xff0c;我们必须把它量化、可视化。那么&#xff0c;因为是UI组件优化&#xff0c;我首先选用了GPU呈现模式分析这一工具。 在手机…

高斯双边滤波

note 原理:从空间维度和灰度维度生成两个高斯滤波器&#xff0c;再合成一个高斯滤波器 空间域高斯滤波器:GaussSpace(x,y) exp(-1 * (x*x y*y) / 2 / sigma / sigma) / 2 / PI / sigma / sigma&#xff1b; 灰度域(颜色域)高斯滤波器:GaussColor(x,y) exp(-1 * (f(x,y) -…

Android性能优化

Android性能优化 一、卡顿优化 前言&#xff1a;说到卡顿我们可能正常能想到是FPS刷新率&#xff0c;这是一个平均值&#xff0c;FPS高并不代表页面流畅&#xff0c;比如一个页面某一贞耗时了160毫秒&#xff0c;但是其他都是16毫秒&#xff0c;那么这个页面通过FPS的数据来看…

Java去重的终极指南:性能对比与高效实现

文章目录 前言一、使用Set接口下面是对几种Set实现类的简单介绍及代码示例&#xff1a;1.HashSet&#xff1a;2.LinkedHashSet&#xff1a;3.TreeSet&#xff1a; 二、使用Stream API三、其他方式1.使用Collectors.toSet()方法&#xff1a;配合Stream API的collect()方法&#…

vue3+cesium项目搭建

前言 最近需要在一个Vue3的项目中使用到cesium&#xff0c;对于一个cesium没有太多了解的人来说&#xff0c;还是比较麻烦的&#xff0c;本篇博文就将自己在这个过程踩的坑记录下来&#xff0c;有需要的可以看一下 1、vuecesium框架搭建 2、项目运行起来后&#xff0c;球体不…