1
Marharyta Nedzelska
Software Engineer @ Wix.com
Building Microservices With Kotlin and gRPC
marharytan@wix.com twitter@jMargaritaN github.com/leveretka
2
Who am I?
Building Microservices with Kotlin and gRPC
Marharyta Nedzelska
3
One more thing you should know
Building Microservices with Kotlin and gRPC
I like boxing!
So think twice before asking tricky questions!
4
AGENDA
Why gRPC?
Protobuf
Implement Service
Error Handling
Testing
More libs for Kotlin
5
AGENDA
Why gRPC?
Protobuf
Implement Service
Error Handling
Testing
More libs for Kotlin
6
Who writes microservices today, please, raise your hands?
7
Microservices Rock!
Building Microservices with Kotlin and gRPC
8
9
The biggest issue in changing a monolith into microservices lies in changing the communication pattern.
Btw, who said this?
Darth Vader
10
11
The biggest issue in changing a monolith into microservices lies in changing the communication pattern.
Btw, who said this?
Darth Vader
12
The biggest issue in changing a monolith into microservices lies in changing the communication pattern.
Btw, who said this?
Martin Fowler
13
Who uses http 1.1 and REST today, please, raise your hands?
14
Clients
Servers
15
Why
gRPC?
01
16
Why gRPC?
Building Microservices with Kotlin and gRPC
17
1991
http 0.9
Http protocol evolution
Building Microservices with Kotlin and gRPC
1996
http 1.0
1997
http 1.1
18
Http protocol evolution
Building Microservices with Kotlin and gRPC
No progress here
2000
1999
1998
19
Http protocol evolution
Building Microservices with Kotlin and gRPC
And here
2003
2002
2001
20
Http protocol evolution
Building Microservices with Kotlin and gRPC
And still no progress...
2006
2005
2004
21
Http protocol evolution
Building Microservices with Kotlin and gRPC
Are they alive?
2009
2008
2007
22
Http protocol evolution
Building Microservices with Kotlin and gRPC
I guess no...
2012
2011
2010
23
Http protocol evolution
Building Microservices with Kotlin and gRPC
And suddenly!
2015
2014
2013
24
Http protocol evolution
Building Microservices with Kotlin and gRPC
2015
http/2
25
Why gRPC?
Building Microservices with Kotlin and gRPC
26
Why gRPC?
Building Microservices with Kotlin and gRPC
27
Why gRPC?
Building Microservices with Kotlin and gRPC
28
Why gRPC?
Building Microservices with Kotlin and gRPC
29
Why gRPC?
Building Microservices with Kotlin and gRPC
30
31
+
ScalaPB
32
?
33
AGENDA
Why gRPC?
Protobuf
Implement Service
Error Handling
Testing
More libs for Kotlin
34
Protocol
Buffers
02
35
Protocol buffers are Google’s language-neutral, platform-neutral, extensible mechanism for serializing structured data — think XML, but smaller, faster, and simpler.
https://developers.google.com/protocol-buffers/
36
Sample .proto file
Building Microservices with Kotlin and gRPC
syntax = "proto3";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
37
Protobuf summary
Building Microservices with Kotlin and gRPC
38
Protobuf summary
Building Microservices with Kotlin and gRPC
39
Protobuf summary
Building Microservices with Kotlin and gRPC
40
Protobuf summary
Building Microservices with Kotlin and gRPC
41
Protobuf summary
Building Microservices with Kotlin and gRPC
42
AGENDA
Why gRPC?
Protobuf
Implement Service
Interceptors
Flow Control
Error Handling
Testing
More libs for Kotlin
43
Implement Service
03
44
What does ‘gRPC’ stand for?
Riddle
45
“gRPC” means gRPC Remote Procedure Call
46
Building Microservices with Kotlin and gRPC
47
Let’s help gRPC team and think of other possible meanings!
48
Task for this session
Building Microservices with Kotlin and gRPC
49
Application is here !
http://104.197.77.39:8080
50
Statistics stream
Messages stream
Building Microservices with Kotlin and gRPC
chat-service
stats-service
Join
Join
When user joins chat...
Messages stream
51
New gRPC meaning
Chat Message
Building Microservices with Kotlin and gRPC
chat-service
stats-service
Chat
When user chats...
Chat Message
Stats
52
Update votes
Building Microservices with Kotlin and gRPC
vote-service
stats-service
Vote
When user votes...
New vote
Stats
53
First iteration is done!
Building Microservices with Kotlin and gRPC
54
First iteration is done!
Building Microservices with Kotlin and gRPC
55
First iteration is done!
Building Microservices with Kotlin and gRPC
56
First iteration is done!
Building Microservices with Kotlin and gRPC
57
First iteration is done!
Building Microservices with Kotlin and gRPC
58
First iteration is done!
Building Microservices with Kotlin and gRPC
59
AGENDA
Why gRPC?
Protobuf
Implement Service
Error Handling
Testing
More libs for Kotlin
60
Error Handling
04
61
All happy families are alike; each unhappy family is unhappy in its own way.
Btw, who said this?
Leo Tolstoy
62
Success
OK
Building Microservices with Kotlin and gRPC
63
Error
Building Microservices with Kotlin and gRPC
64
Error
Building Microservices with Kotlin and gRPC
65
Error
Building Microservices with Kotlin and gRPC
66
What about custom exceptions?
Building Microservices with Kotlin and gRPC
67
What about custom exceptions?
Building Microservices with Kotlin and gRPC
68
Server interceptor
Use close method to change returned status
override fun <ReqT, RespT> interceptCall(call: ServerCall<ReqT, RespT>,
headers: Metadata, next: ServerCallHandler<ReqT, RespT>) : ServerCall.Listener<ReqT> {
val wrappedCall = object : ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT>(call) {
override fun close(status: Status, trailers: Metadata) {
var status = status
if (status.code == Status.Code.UNKNOWN && status.description == null
&& status.cause != null && throwables.contains(status.cause!!.javaClass)) {
val t = status.cause
status = Status.INTERNAL.withDescription(t!!.message)
.augmentDescription(stacktraceToString(t))
}
super.close(status, trailers)
}
}
return next.startCall(wrappedCall, headers)
}
69
Server interceptor
Use close method to change returned status
override fun <ReqT, RespT> interceptCall(call: ServerCall<ReqT, RespT>,
headers: Metadata, next: ServerCallHandler<ReqT, RespT>) : ServerCall.Listener<ReqT> {
val wrappedCall = object : ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT>(call) {
override fun close(status: Status, trailers: Metadata) {
var status = status
if (status.code == Status.Code.UNKNOWN && status.description == null
&& status.cause != null && throwables.contains(status.cause!!.javaClass)) {
val t = status.cause
status = Status.INTERNAL.withDescription(t!!.message)
.augmentDescription(stacktraceToString(t))
}
super.close(status, trailers)
}
}
return next.startCall(wrappedCall, headers)
}
70
What about custom exceptions?
Building Microservices with Kotlin and gRPC
71
Client
Catch Status Runtime Exception
try {
stub.doSth(request)
} catch (e: StatusRuntimeException) {
logger.log(Level.SEVERE, e.message, e)
}
72
AGENDA
Why gRPC?
Protobuf
Implement Service
Error Handling
Testing
More libs for Kotlin
73
Testing
05
74
75
Unit testing
Building Microservices with Kotlin and gRPC
76
Let’s test chat method on server
lateinit var server: Server
lateinit var inProcessChannel: ManagedChannel
@Before
@Throws(Exception::class)
fun setUp() {
val serverName = InProcessServerBuilder.generateName()
server = InProcessServerBuilder.forName(serverName).directExecutor()
.addService(ManualFlowChatServiceImpl())
.build().start()
inProcessChannel = InProcessChannelBuilder.forName(serverName).directExecutor().build()
}
Building Microservices with Kotlin and gRPC
77
Let’s test chat method on server
lateinit var server: Server
lateinit var inProcessChannel: ManagedChannel
@Before
@Throws(Exception::class)
fun setUp() {
val serverName = InProcessServerBuilder.generateName()
server = InProcessServerBuilder.forName(serverName).directExecutor()
.addService(ChatServiceImpl())
.build().start()
inProcessChannel = InProcessChannelBuilder.forName(serverName).directExecutor().build()
}
Building Microservices with Kotlin and gRPC
78
Unit testing
Building Microservices with Kotlin and gRPC
79
Let’s test chat method on server
@RunWith(JUnit4::class)
class ChatServiceTest {
lateinit var server: Server
lateinit var inProcessChannel: ManagedChannel
...
@After
fun tearDown() {
inProcessChannel.shutdown()
server.shutdown()
}
...
}
Building Microservices with Kotlin and gRPC
80
Unit testing
Building Microservices with Kotlin and gRPC
81
Let’s test chat method on server
@Test
fun chatTest() {
val stub = ChatServiceGrpc.newStub(inProcessChannel)
val responseObserver: StreamObserver<ChatProto.ChatMessage> = mock { }
val requestObserver = stub.chat(responseObserver)
val chatMessage = ChatMessage.newBuilder().setFrom("Margo").setContent("Hello!").build()
val chatMessageCaptor: ArgumentCaptor<ChatProto.ChatMessage> =
ArgumentCaptor.forClass(ChatMessage::class.java)
requestObserver.onNext(chatMessage)
chatMessageCaptor.run {
verify(responseObserver).onNext(capture())
assertEquals("Margo", value.from)
assertEquals("Hello!", value.content)
}
}
Building Microservices with Kotlin and gRPC
82
Let’s test chat method on server
@Test
fun chatTest() {
val stub = ChatServiceGrpc.newStub(inProcessChannel)
val responseObserver: StreamObserver<ChatProto.ChatMessage> = mock { }
val requestObserver = stub.chat(responseObserver)
val chatMessage = ChatMessage.newBuilder().setFrom("Margo").setContent("Hello!").build()
val chatMessageCaptor: ArgumentCaptor<ChatProto.ChatMessage> =
ArgumentCaptor.forClass(ChatMessage::class.java)
requestObserver.onNext(chatMessage)
chatMessageCaptor.run {
verify(responseObserver).onNext(capture())
assertEquals("Margo", value.from)
assertEquals("Hello!", value.content)
}
}
Building Microservices with Kotlin and gRPC
83
What about integration
and e2e test?
84
85
If you made a death star
86
You should provide staff to test it!
87
Testing summary
Building Microservices with Kotlin and gRPC
88
Testing summary
Building Microservices with Kotlin and gRPC
89
Testing summary
Building Microservices with Kotlin and gRPC
90
Testing summary
Building Microservices with Kotlin and gRPC
91
AGENDA
Why gRPC?
Protobuf
Implement Service
Error Handling
Testing
More libs for Kotlin
92
More libs for
Kotlin
06
93
Building Microservices with Kotlin and gRPC
94
Building Microservices with Kotlin and gRPC
95
Expectation
Building Microservices with Kotlin and gRPC
96
Reality
Building Microservices with Kotlin and gRPC
97
https://github.com/rouzwawi/grpc-kotlin.git
98
https://github.com/rouzwawi/grpc-kotlin.git
99
https://github.com/rouzwawi/grpc-kotlin.git
100
https://github.com/marcoferrer/kroto-plus.git
101
Examples
�//Kroto+ Overloaded�val response = serviceStub.myRpcMethod {� id = 100� name = "some name"� }
Building Microservices with Kotlin and gRPC
102
Examples
suspend fun findStrongestAttack(): StandProto.Attack {� val standService = StandServiceGrpc.newStub(managedChannel)� val characterService = CharacterServiceGrpc.newStub(managedChannel)� val deferredStands = characterService.getAllCharactersStream()� .map { character ->� async { standService.getStandByCharacter(character) }� }.toList()� val strongestAttack = deferredStands� .flatMap { it.await().attacksList }� .maxBy { it.damage } � return strongestAttack ?: StandProto.Attack.getDefaultInstance()}
Building Microservices with Kotlin and gRPC
103
Examples
suspend fun findStrongestAttack(): StandProto.Attack {� val standService = StandServiceGrpc.newStub(managedChannel)� val characterService = CharacterServiceGrpc.newStub(managedChannel)� val deferredStands = characterService.getAllCharactersStream()� .map { character ->� async { standService.getStandByCharacter(character) }� }.toList()� val strongestAttack = deferredStands� .flatMap { it.await().attacksList }� .maxBy { it.damage } � return strongestAttack ?: StandProto.Attack.getDefaultInstance()}
Building Microservices with Kotlin and gRPC
104
Examples
val attack = Attack {� name = "ORA ORA ORA"� damage = 100� range = StandProto.Attack.Range.CLOSE}�//Copy extensions are also generated�val newAttack = attack.copy { damage = 200 } ��//As well as plus operator extensions �val mergedAttack = attack + Attack { name = "Sunlight Yellow Overdrive" }
Building Microservices with Kotlin and gRPC
105
One day we’ll have proper kotlin support
106
Takeaways
INSERT YOUR�TOPIC NAME
107
My gRPC Kotlin Sandbox
https://github.com/leveretka/grpc-chat.git
108
Time to define winner!
109
Thank You
marharytan@wix.com twitter@jMargaritaN github.com/leveretka
110
Q&A
marharytan@wix.com twitter@jMargaritaN github.com/leveretka