Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
grpc-kotlinはどこまでKotlin化できるのか?
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Takehata Naoto
June 17, 2020
Programming
0
990
grpc-kotlinはどこまでKotlin化できるのか?
2020年6月17日(水) 「集まれKotlin好き!Kolint愛好会 vol.22 @オンライン」の談義資料です。
Takehata Naoto
June 17, 2020
Tweet
Share
More Decks by Takehata Naoto
See All by Takehata Naoto
KotlinConf 2025で発表された言語のアップデートと現地参加レポート
n_takehata
2
350
KotlinConf 2025 現地で感じたServer-Side Kotlin
n_takehata
2
410
KotlinConf 2025 現地参加の土産話
n_takehata
0
180
組織貢献をするフリーランスエンジニアという生き方
n_takehata
1
5.7k
「2024年版 Kotlin サーバーサイドプログラミング実践開発」の補講 〜O/Rマッパー編〜
n_takehata
2
780
2024年版 Kotlin サーバーサイドプログラミング実践開発
n_takehata
9
8.4k
Server-Side目線で見る、Kotlin Festの楽しみ方
n_takehata
0
580
KotlinとCloud Vision APIで領収書の電子帳簿保存法対応をする
n_takehata
1
1.8k
KotlinConf 2023 現地参加レポート
n_takehata
1
390
Other Decks in Programming
See All in Programming
LLM Observabilityによる 対話型音声AIアプリケーションの安定運用
gekko0114
2
440
AIエージェントのキホンから学ぶ「エージェンティックコーディング」実践入門
masahiro_nishimi
6
680
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
620
16年目のピクシブ百科事典を支える最新の技術基盤 / The Modern Tech Stack Powering Pixiv Encyclopedia in its 16th Year
ahuglajbclajep
5
1k
今こそ知るべき耐量子計算機暗号(PQC)入門 / PQC: What You Need to Know Now
mackey0225
3
390
Vibe Coding - AI 驅動的軟體開發
mickyp100
0
180
Automatic Grammar Agreementと Markdown Extended Attributes について
kishikawakatsumi
0
200
AIによる開発の民主化を支える コンテキスト管理のこれまでとこれから
mulyu
3
510
Fluid Templating in TYPO3 14
s2b
0
130
QAフローを最適化し、品質水準を満たしながらリリースまでの期間を最短化する #RSGT2026
shibayu36
2
4.4k
OCaml 5でモダンな並列プログラミングを Enjoyしよう!
haochenx
0
150
コマンドとリード間の連携に対する脅威分析フレームワーク
pandayumi
1
470
Featured
See All Featured
It's Worth the Effort
3n
188
29k
sira's awesome portfolio website redesign presentation
elsirapls
0
150
Balancing Empowerment & Direction
lara
5
900
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
196
71k
Utilizing Notion as your number one productivity tool
mfonobong
3
220
Java REST API Framework Comparison - PWX 2021
mraible
34
9.2k
Producing Creativity
orderedlist
PRO
348
40k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.4k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.1k
Are puppies a ranking factor?
jonoalderson
1
2.7k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
0
1.1k
Bash Introduction
62gerente
615
210k
Transcript
grpc-kotlinはどこまでKotlin化できるのか? 2020年6月17日 Kotlin愛好会 vol.22 竹端 尚人
自己紹介
概要 氏名:竹端 尚人 Twitter:@n_takehata ・サーバーサイドKotlin ・(少し前まで)スマートフォンゲーム開発 ・今月転職して新しい会社で???を開発
登壇、執筆など ・CEDEC 2018登壇 ・Software Design 2019年2〜4月号で短期連載 ・Swift/Kotlin愛好会で技術書典執筆 https://booth.pm/ja/items/1315478
今日話すこと
grpc-java -> gprc-kotlin • 今年の4月にgrpc-kotlinがリリース • これまでKotlinでgRPCを使うにはgrpc-javaを使用していたが、 待望のKotlinのライブラリが登場 • ただし、まだ全てをKotlin化できるわけではない
grpc-kotlinを使うGradleの依存関係(抜粋) implementation "io.grpc:grpc-kotlin-stub:$grpc_kotlin_version" implementation "com.google.protobuf:protobuf-java:$protobuf_version" implementation "com.google.protobuf:protobuf-java-util:$protobuf_version" implementation "io.grpc:grpc-netty-shaded:$grpc_version" implementation
"io.grpc:grpc-protobuf:$grpc_version" implementation "io.grpc:grpc-stub:$grpc_version" Javaのライブラリも併せて必要
コード生成のGradleタスク(抜粋) Javaのコード生成も必要 plugins { grpc { artifact = "io.grpc:protoc-gen-grpc-java:$grpc_version" }
grpckt { artifact = "io.grpc:protoc-gen-grpc-kotlin:$grpc_kotlin_version" } }
gRPCの実装を どこまでKotlin化できるのかを紹介します
アジェンダ 1.どこをKotlin化できるのか? 2.Service 3.Stub 4.Javaのままの箇所 5.grpc-spring-boot-starterと組み合わせて使う
1.どこをKotlin化できるのか?
gRPC実装時の主な要素 • サーバー • Service • ServerInterceptor • クライアント •
Channel • Stub • ClientInterceptor • 共通 • message
gRPC実装時の主な要素 • サーバー • Service • ServerInterceptor • クライアント •
Channel • Stub • ClientInterceptor • 共通 • message
Service、Stubの部分がKotlin化できる
2.Service
実装比較
grpc-javaでの実装(抜粋) class GreeterImpl : GreeterGrpc.GreeterImplBase() { override fun sayHello(req: HelloRequest,
responseObserver: StreamObserver<HelloReply>) { val reply = HelloReply.newBuilder().setMessage("Hello ${req.name}").build() responseObserver.onNext(reply) responseObserver.onCompleted() } } Observerパターンで実装されている
grpc-kotlinでの実装(抜粋) class HelloWorldService : GreeterGrpcKt.GreeterCoroutineImplBase() { override suspend fun sayHello(request:
HelloRequest) = HelloReply .newBuilder() .setMessage("Hello ${request.name}") .build() } ・親クラスをKotlin化したものに変更 ・suspend関数に変更 ・Observerを使わなくなった
ただし
CoroutineServiceの親クラス(抜粋) Javaのクラスを継承している(Javaに依存している) abstract class AbstractCoroutineServerImpl( /** The context in which
to run server coroutines. */ val context: CoroutineContext = EmptyCoroutineContext ) : BindableService {
3.Stub
実装比較
grpc-javaでの実装(抜粋) fun greet(name: String) { val blockingStub: GreeterGrpc.GreeterBlockingStub = GreeterGrpc.newBlockingStub(channel)
val request = HelloRequest.newBuilder().setName(name).build() val response: HelloReply = blockingStub.sayHello(request) logger.info("Greeting: ${response.message}") } Stubを生成して実行
grpc-kotlinでの実装(抜粋) suspend fun greet(name: String) = coroutineScope { val stub:
GreeterCoroutineStub = GreeterCoroutineStub(channel) val request = HelloRequest.newBuilder().setName(name).build() val response = async { stub.sayHello(request) } println("Received: ${response.await().message}") } ・Kotlin化されたStubを使う ・Stubの関数もsuspend関数になっているため、非同期で実行する
ただし
Stubの親クラス abstract class AbstractCoroutineStub<S: AbstractCoroutineStub<S>>( channel: Channel, callOptions: CallOptions =
CallOptions.DEFAULT ): AbstractStub<S>(channel, callOptions) Serviceと同様Javaのクラスを継承している(Javaに依存している)
4.Javaのままの箇所
Javaのままの箇所 • ServerInterceptor • ClientInterceptor • Channel • message
ServerInterceptor @GRpcGlobalInterceptor @Order(10) class LoggingInterceptor : ServerInterceptor { companion object
{ private val log = LoggerFactory.getLogger(LoggingInterceptor::class.java) } override fun <ReqT : Any, RespT : Any> interceptCall(call: ServerCall<ReqT, RespT>, headers: Metadata, next: ServerCallHandler<ReqT, RespT>): ServerCall.Listener<ReqT> { log.info("method name=${call.methodDescriptor.fullMethodName}") return next.startCall(call, headers) } }
ClientIterceptor class MetadataClientInterceptor : ClientInterceptor { companion object { private
val log = LoggerFactory.getLogger(MetadataClientInterceptor::class.java) } override fun <ReqT, RespT> interceptCall(method: MethodDescriptor<ReqT, RespT>?, callOptions: CallOptions?, next: Channel): ClientCall<ReqT, RespT>? { return object : SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) { override fun start(responseListener: Listener<RespT>?, headers: Metadata) { headers.put(Metadata.Key.of(“example”, Metadata.ASCII_STRING_MARSHALLER), “Example”) // ・・・
Channel、message suspend fun greet(name: String) = coroutineScope { val channel
= ManagedChannelBuilder.forAddress("localhost", 6565) .usePlaintext().build() val stub: GreeterCoroutineStub = GreeterCoroutineStub(channel) val request = HelloRequest.newBuilder().setName(name).build() val response = async { stub.sayHello(request) } println("Received: ${response.await().message}") }
messageをもしデータクラスにできたら・・・ suspend fun greet(name: String) = coroutineScope { val channel
= ManagedChannelBuilder.forAddress("localhost", 6565) .usePlaintext().build() val stub: GreeterCoroutineStub = GreeterCoroutineStub(channel) val request = HelloRequest (name) val response = async { stub.sayHello(request) } println("Received: ${response.await().message}") }
5.grpc-spring-boot-starterと組み合わせて使う
Gradleの依存関係
grpc-kotlinを使うGradleの依存関係(再掲) implementation "io.grpc:grpc-kotlin-stub:$grpc_kotlin_version" implementation "com.google.protobuf:protobuf-java:$protobuf_version" implementation "com.google.protobuf:protobuf-java-util:$protobuf_version" implementation "io.grpc:grpc-netty-shaded:$grpc_version" implementation
"io.grpc:grpc-protobuf:$grpc_version" implementation "io.grpc:grpc-stub:$grpc_version"
spring-boot-starterを使う場合の依存関係(抜粋) implementation "org.springframework.boot:spring-boot-starter-webflux” implementation "io.github.lognet:grpc-spring-boot-starter:$grpc_spring_boot_version" implementation "io.grpc:grpc-kotlin-stub:$grpc_kotlin_version”
サーバーの実装比較
grpc-javaでの実装(抜粋) @GRpcService(interceptors = [MessageInterceptor::class]) class ExampleGrpcService : ExampleGrpc.ExampleImplBase() { override
fun createMessage(request: CreateMessageRequest, responseObserver: StreamObserver<CreateMessageResponse>) { // ・・・
grpc-kotlinでの実装(抜粋) @GRpcService(interceptors = [MessageInterceptor::class]) class ExampleGrpcService : ExampleGrpcKt.ExampleCoroutineImplBase() { override
suspend fun createMessage(request: CreateMessageRequest): CreateMessageResponse { // ・・・ もともとの実装にgrpc-kotlinを組み込んだ形
クライアントの実装比較 (Controllerからの呼び出しを例に)
grpc-javaでの実装(抜粋) @RequestMapping("/createmessage") fun createMessage(@RequestBody request: RestCreateMessageRequest): String { val createMessageRequest
= CreateMessageRequest.newBuilder().setName(request.name).build() val channel = ManagedChannelBuilder.forAddress("localhost", 6565) .usePlaintext().build() val stub = ExampleGrpc.newBlockingStub(channel) val response = stub.createMessage(createMessageRequest) return response.message.text }
grpc-kotlinでの実装(抜粋) @PostMapping("/createmessage") suspend fun createMessage(@RequestBody request: RestCreateMessageRequest): String { val
createMessageRequest = CreateMessageRequest.newBuilder().setName(request.name).build() val channel = ManagedChannelBuilder.forAddress("localhost", 6565) .usePlaintext().build() val stub = ExampleGrpcKt.ExampleCoroutineStub(channel) val response = async { stub.createMessage(createMessageRequest) } return response.await().message.text }
• Stubの関数がsuspend関数なので、Controllerまでsuspendが連鎖する • 通常のSpring BootではControllerをsuspend関数にできず、 runBlockingなどする必要がある
spring-boot-starterを使う場合の依存関係(抜粋) implementation "org.springframework.boot:spring-boot-starter-webflux” implementation "io.github.lognet:grpc-spring-boot-starter:$grpc_spring_boot_version" implementation "io.grpc:grpc-kotlin-stub:$grpc_kotlin_version” Spring WebFluxを使うと非同期I/Oが実現できる
KotlinでSpring Boot使うなら WebFluxにしたい
まとめ
• Service、Stubに関してはKotlin化できる • ただし親クラスがJavaだったり、Javaのライブラリを呼んでいたりと依存 はしている • spring-boot-starterとの組み合わせは問題なさそう
https://blog.takehata-engineer.com/entry/change-to-kotlin- by-grpc-kotlin こちらのブログもご御覧ください grpc-kotlinはgRPCの実装をどこまでKotlin化できるのか? grpc-kotlinをgrpc-spring-boot-starterと組み合わせて使う https://blog.takehata-engineer.com/entry/grpc-kotlin-with- grpc-spring-boot-starter
ご清聴ありがとうございました