Slide 1

Slide 1 text

サーバーサイドKotlinでgRPCをやってみよう ⽵端 尚⼈ @n_takehata 2019/9/9 Kotlin Fest Reject Conference 2019

Slide 2

Slide 2 text

⾃⼰紹介

Slide 3

Slide 3 text

概要 ⽵端 尚⼈ 所属:株式会社アプリボット 職種:バックエンドエンジニア 好きな⾔語:Kotlin Twitter:@n_takehata 2006.04 公務員 2007.12 SES 2011.01 サイバーエージェント 2014.04 アプリボット

Slide 4

Slide 4 text

登壇、執筆など • CEDEC 2018、2019登壇 https://speakerdeck.com/n_takehata/cedec- 2018 • Kotlin Fest 2018登壇(LT⼤会) • 雑誌Software Design 2019年2〜4⽉号に てサーバーサイドKotlinについての短期連 載執筆

Slide 5

Slide 5 text

Kotlin Fest 2019に申し込んだテーマ

Slide 6

Slide 6 text

Kotlin × gRPCを使⽤した次世代のサーバーサイド開発

Slide 7

Slide 7 text

Rejected…

Slide 8

Slide 8 text

セッション⼀覧をよく⾒ると

Slide 9

Slide 9 text

gRPCよりGraphQLなのか︕︕

Slide 10

Slide 10 text

サーバーサイドKotlinでgRPCをやってみよう ⽵端 尚⼈ @n_takehata 2019/9/9 Kotlin Fest Reject Conference 2019 タイトルパクりました ※ @shiraj_iさんごめんなさい

Slide 11

Slide 11 text

今⽇はgRPCもいいなって 思ってもらいたいです︕

Slide 12

Slide 12 text

アジェンダ 1.gRPCとはなにか? 2.Protocol Buffersについて 3.サーバーサイドKotlinでgRPCを使うには

Slide 13

Slide 13 text

2019/9/9 gRPCとはなにか︖ 1

Slide 14

Slide 14 text

gRPCとは︖ • Google製のRPCフレームワーク • HTTP/2、Protocol Bufferesを標準でサポートし、ハイパ フォーマンスな通信を実現 • RESTに代わる通信⽅式の⼀つとしても期待されている

Slide 15

Slide 15 text

特徴

Slide 16

Slide 16 text

• Protocol Bufferesによるインターフェース定義共通化 • Java、C#、Goなど様々な⾔語に対応 • 各⾔語のコード⾃動⽣成が可能 • HTTP/2による⾼速で柔軟な通信

Slide 17

Slide 17 text

パフォーマンス(RESTとの⽐較)

Slide 18

Slide 18 text

平均リクエスト時間 (ms) 平均レスポンス時間 (ms) gRPC 2.92 3.6 REST 7.16 12.78 ※2018年3⽉当時の検証結果です リクエストが約2倍、レスポンスが約4倍速かった (条件付き)

Slide 19

Slide 19 text

2019/9/9 Protocol Buffersについて 2

Slide 20

Slide 20 text

Protocol Buffersとは︖ • 通信のインターフェースを定義できるIDLの⼀種 • protocというコマンドで、定義ファイルからインターフェース に合わせた様々な⾔語のコードを⽣成できる (Java、C#、C++、Python、Go、Ruby、PHP、Dart) • 定義した構造のバイナリデータで通信する

Slide 21

Slide 21 text

サンプル

Slide 22

Slide 22 text

①リクエスト、レスポンスのパラメータを定義 ②APIのインターフェースを定義 .protoという拡張⼦で定義 service Greeter { rpc SayHello (HelloRequest) returns (HelloReply); } message HelloRequest { string name = 1; } message HelloReply { string message = 1; } ① ②

Slide 23

Slide 23 text

使いたい⾔語を指定してコンパイル

Slide 24

Slide 24 text

protocコマンドの例(Golang) protoc --go_out=plugins=grpc:../pb hello.proto

Slide 25

Slide 25 text

⽣成されるコード • Messageのデータ構造に合わせたModelクラス • データのシリアライズ、デシリアライズ • gRPCのサーバー実装のBaseクラス(プラグイン必要) • gRPCのクライアントStub (プラグイン必要) • etc…

Slide 26

Slide 26 text

コンパイルイメージ

Slide 27

Slide 27 text

⽣成したファイルの実⾏イメージ ⾃動⽣成のServer、Stubのプログラムを介して 通信を実装できる

Slide 28

Slide 28 text

通信部分の実装が容易に • 定義ファイルさえ書けば、パラメータのクラスなどを作成する ⼿間が不要 • サーバー、クライアント間の実装の齟齬も防げる • GraphQLやSwaggerとも通づる機構

Slide 29

Slide 29 text

2019/9/9 サーバーサイドKotlinでgRPCを使うには 2

Slide 30

Slide 30 text

KotlinでのgRPCを使うには • ⾃動⽣成のコードはJavaで作成する(Kotlinには⾮対応) • Spring Bootを使っている場合はgrpc-spring-boot-starterを使う のが⼿軽 • コード⽣成はprotocを直接使わず、Gradleプラグインで実⾏で きる

Slide 31

Slide 31 text

⼿順

Slide 32

Slide 32 text

Gradleにプラグイン、依存関係を追加 compile("io.github.lognet:grpc-spring-boot-starter:3.3.0") id("com.google.protobuf") version "0.8.9" ①Protocol Buffersをコンパイルするためのプラグイン ②Spring BootでgRPCを扱うためのStarter

Slide 33

Slide 33 text

コードジェネレータの設定 ①使⽤するprotocのライブラリ、バージョンを指定 ②gRPCのコードを⽣成するプラグインを指定 protobuf { protoc { artifact = "com.google.protobuf:protoc:3.5.1-1" } plugins { grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" } } generateProtoTasks { all().each { task -> task.plugins { grpc } } } generatedFilesBaseDir = "$projectDir/src/" } ① ②

Slide 34

Slide 34 text

コンパイルタスクの実⾏ generateProtoタスクがprotocを実⾏ ./gradlew generateProto

Slide 35

Slide 35 text

ファイルが⽣成される • xxxOuterClass.java • service、messageで定義したクラスを含むクラス • シリアライズ、デシリアライズなどをやってくれる • xxxGrpc.java • xxxOuterClassを使⽤してgRPCで通信するサーバー処理やクライアン トStubなどを含んだクラス

Slide 36

Slide 36 text

サーバー側のコードの実装 ①⾃動⽣成のBaseクラスを継承 ②gRPCのサービスとして起動時に読み込ませるアノテーション @GRpcService class GreeterService: GreeterGrpc.GreeterImplBase() { override fun sayHello(request: HelloRequest, responseObserver: StreamObserver) { val replyBuilder = HelloReply.newBuilder().setMessage("Hello " + request.name) responseObserver.onNext(replyBuilder.build()) responseObserver.onCompleted() } } ① ②

Slide 37

Slide 37 text

クライアント側のコードの実装 ①接続の設定 ②Stubのインスタンス⽣成 ③Stubのメソッド実⾏ fun execSayHello(name: String) { val request = HelloRequest.newBuilder().setName(name).build() val channel = ManagedChannelBuilder.forAddress("localhost", 6565).build() val stub = GreeterGrpc.newBlockingStub(channel) stub.sayHello(request) } ① ② ③

Slide 38

Slide 38 text

まとめ

Slide 39

Slide 39 text

サーバーサイドKotlinでgRPCを使うには • Gradleにprotobufのプラグイン、grpc-spring-boot-starterの依存関係 を追加 • protoファイルを定義しコンパイル • ⽣成されたコードを継承し、アノテーションを付けて実装 参考: https://blog.takehata-engineer.com/entry/server-side-kotlin-grpc-project- creation-to-start-confirmation

Slide 40

Slide 40 text

ご清聴ありがとうございました