SpringBoot+Kotlin中使用GRPC实现服务通信的示例代码

 更新时间:2023年07月11日 14:38:44   作者:了迹奇有没  
本文主要介绍了SpringBoot+Kotlin中使用GRPC实现服务通信的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

示例项目见: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 版本的,如果你的版本不适配,可能也需要折腾一下,但问题应该不是很大。

到此这篇关于SpringBoot+Kotlin中使用GRPC实现服务通信的示例代码的文章就介绍到这了,更多相关SpringBoot Kotlin GRPC服务通信内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解SpringBoot Start组件开发之记录接口日志信息

    详解SpringBoot Start组件开发之记录接口日志信息

    这篇文章主要为大家介绍了SpringBoot-Start组件开发之记录接口日志信息详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • Spring Boot文件上传原理与实现详解

    Spring Boot文件上传原理与实现详解

    这篇文章主要介绍了Spring Boot 文件上传原理与实现详解,前端文件上传是面向多用户的,多用户之间可能存在上传同一个名称、类型的文件;为了避免文件冲突导致的覆盖问题这些应该在后台进行解决,需要的朋友可以参考下
    2024-01-01
  • spring 注解验证@NotNull等使用方法

    spring 注解验证@NotNull等使用方法

    这篇文章主要介绍了spring 注解验证@NotNull等使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • 一道关于java异常处理的题目

    一道关于java异常处理的题目

    本文给大家分享一道关于java异常处理的题目,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-09-09
  • Java并发工具之CyclicBarrier使用详解

    Java并发工具之CyclicBarrier使用详解

    这篇文章主要介绍了Java并发工具之CyclicBarrier使用详解,CyclicBarrier是一个同步器,允许一组线程相互之间等待,直到到达某个公共屏障点(common barrier point),再继续执行,需要的朋友可以参考下
    2023-12-12
  • Java Web 实现QQ登录功能一个帐号同一时间只能一个人登录

    Java Web 实现QQ登录功能一个帐号同一时间只能一个人登录

    对于一个帐号在同一时间只能一个人登录,下文给大家介绍的非常详细,对java web qq 登录功能感兴趣的朋友一起看看吧
    2016-11-11
  • eclipse中自动生成构造函数的两种方法

    eclipse中自动生成构造函数的两种方法

    下面小编就为大家带来一篇eclipse中自动生成构造函数的两种方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • 关于IDEA报错Error:java 不支持发行版本17的原因及解决方案

    关于IDEA报错Error:java 不支持发行版本17的原因及解决方案

    在rebuild或运行项目时提示“Error:java: 错误: 不支持发行版本 17”,本文将给大家介绍了IDEA提示“Error:java: 错误: 不支持发行版本17”的原因及解决方案,需要的朋友可以参考下
    2023-09-09
  • 详解Springboot @Cacheable 注解(指定缓存位置)

    详解Springboot @Cacheable 注解(指定缓存位置)

    这篇文章主要介绍了详解Springboot @Cacheable 注解(指定缓存位置),使用  @Cacheable  注解就可以将运行结果缓存,以后查询相同的数据,直接从缓存中取,不需要调用方法,需要的朋友可以参考下
    2023-09-09
  • java使用Socket实现SMTP协议发送邮件

    java使用Socket实现SMTP协议发送邮件

    这篇文章主要为大家详细介绍了java使用Socket实现SMTP协议发送邮件的相关资料,感兴趣的小伙伴们可以参考一下
    2016-05-05

最新评论